类的const成员函数

本文详细解析了C++中const成员函数的概念及其使用限制,包括如何正确地从const成员函数返回*this,以及如何通过重载解决返回*this带来的问题。同时介绍了mutable关键字的作用及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类的const成员函数

class Sales_data
{
public:
    string Get_isbn() const {return bookNo;}
    //const成员函数
pritvate:
    string bookNo;
};

定义为const的成员函数 不可以修改类的数据成员(只读)
在成员函数内使用类的数据成员时,实际上隐式的引入了 this

//以上面的Get_isbn()为例
string Get_isbn() const {return this->bookNo;}
//等价于上面的写法

而紧随参数表之后的const关键字,作用是修改隐式this指针的类型为常量指针


返回*this的成员函数

可以让成员函数返回*this来将调用它的对象返回

class Screen
{
public:
    Screen &Move(int x,int y)
    {
        //省略函数实现
        return *this;          
    }
    Screen &Show()
    {
        //省略实现
        return *this;
    }
};

Screen sc;
sc.Move(1,2).Show();        

从const成员函数返回*this

const成员函数通过*this返回的是常量

const Screen &Display() const 
{
    //省略实现  
    return *this;
}
//返回类型的const不可省略

这样设置其实是很有道理的,试想,将一个成员函数设置为const,目的就是禁止该成员函数修改类内数据成员,使其返回常量(引用)可以禁止间接的修改数据成员。


但这引入了一个新的问题:
一个非常量对象调用了const成员函数后会变成一个常量对象(函数返回引用时为常量引用)

//a example
class A
{
public:
    A &Set(int x)
    {
        val = x;
        return *this;
    }
    const A &Read() const          //一个const成员函数,返回const引用(底层)
    {
        cout<<val<<endl;
        return *this;
    }
private:
    int val;
};

A obj;
obj.Set(5).Read().Set(3);       //ERROR 调用Read()后返回常量引用

为了解决这个问题,我们可以写一个重载,根据调用成员函数的对象本身是常量或非常量来决定调用哪个版本

class Screen
{
public:
    Screen &display(std::ostream &os)
    {
        do_display(os);
        cout<<"1"<<endl;
        return *this;
    }
    const Screen &display(std::ostream &os) const
    {
        do_display(os);
        cout<<"2"<<endl;
        return *this;
    }
private:
    string contents = "test";
    void do_display(std::ostream &os) const
    {
        os<<contents<<endl;              //将“只读”模块封装
    }
}

    Screen obj;                   //非常量对象
    const Screen cobj;            //常量对象(只可以调用常量成员函数)
    obj.display(cout);            //调用非常量版本
    cobj.display(cout);           //调用常量版本

这与我们之前所了解的重载有点不同,函数重载是通过参数表来区分的
而这里的常量与非常量成员函数的重载区分依据是调用他们的对象是常量还是非常量


可变数据成员mutable

一个可变数据成员,永远不会是const
无论是在const对象中还是在const成员函数中都可以修改

class Screen
{
public:
    void func() const
    {
        x = 10;             //即使在const成员函数中也可以修改mutable变量的值 
    }
    void Show() 
    {
        cout << x << endl;
    }
private:
    mutable int x = 0;
};

类的常量对象

用const关键字来定义一个类的常量对象

对于类的函数成员: 常量对象只能访问常量函数成员
对于类的数据成员: 常量对象可以访问数据成员,但不能修改
对于mutable数据成员: 常量对象既可以访问也可以修改

class A
{
public:
    mutable int val;
    int a;

    A(int _val,int _a):val(_val),a(_a) {}
    A& Set(int _val,int _a)
    {
        val = _val;
        a = _a;
    }

    const A& Read() const            //常量函数成员
    {
        cout << val << endl
            << a << endl;
        return *this;
    }
};

const A a(5,10);        //定义一个类的常量对象
a.Read();               //ok
a.Set(1,2);             //error! a只可以访问常量函数成员
a.val = 999;            //ok  常量对象可以改变mutable数据成员
a.a = 999;              //error! 对于普通数据成员,常量对象只能访问不可以修改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值