1.const修饰成员函数规则
我们来看看下面的代码 并思考下面的几个问题: 1. const对象可以调用非const成员函数吗? 2. 非const对象可以调用const成员函数吗? 3. const成员函数内可以调用其它的非const成员函数吗? 4. 非const成员函数内可以调用其它的const成员函数吗?
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << "year:" << _year << endl;
cout << "month:" << _month << endl;
cout << "day:" << _day << endl << endl;
}
private:
int _year;
int _month;
int _day;
};
void Test()
{
Date d1(2024,2,1);
d1.Print();
}
上面这段代码能够正常运行,并将d1日期类打印出来。
那如果在一个对象前面加上const修饰呢?
void Test()
{
Date d1(2024, 2, 1);
d1.Print();
const Date d2(2024, 2, 1);
d2.Print();
}
此段代码在vs编译器下会立马被发现错误。
明明这里打印只是读取里面的内容,并没有修改它的内容,为什么类的对象加上const修饰就无法调用Print函数呢?
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数 隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
而const修饰规则是:权限不能放大 权限既可以缩小,也可以平移,就是不能放大。
将d2传到Print函数里面时,它会用一个指向d2的指针来接收,而且这是默认非const的指针,所以由const保护的类传给非const的函数就是一个典型的权限放大问题。
解决这个问题的办法也很简单:直接用一个const修饰的this指针来修饰不就可以了
但是接收时的this指针不可以显示的写,祖师爷就规定统一将const写到函数括号后面
如此一来,权限的问题就很好的解决了:
void Print() const
{
cout << "year:" << _year << endl;
cout << "month:" << _month << endl;
cout << "day:" << _day << endl << endl;
}
既然我们知道const修饰规则,权限可以缩小,可以平移,不可以放大,那么开头提到的问题都有了答案。
我们很容易发现,不管什么样的对象,都可以调用const修饰的成员函数,那是不是以后直接将所有的成员函数写成const修饰的?
其实写不写const取决于你的需求,如果希望修改里面的内容,就不能用const修饰,否则无法改变里面的内容。但如果不改变里面的内容,只是想读取里面的信息,建议还是用const进行保护,以防我们有朝一日不小心修改了里面的值。
2.const修饰的取地址操作符重载
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
class A
{
public:
Date* operator&()
{
return this;
}
const Date* operator&()const
{
return this;
}
private:
int _year;
int _month;
int _day;
};
因为一个是Date* 一个是const Date* 两种不同的类型,故这里构成函数重载
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需 要重载,比如想让别人获取到指定的内容!