假设定义了一个类A,A包含一个int类型的数据成员n、print成员函数和set成员函数,print成员函数打印n值,set成员函数改变n值。由于print不会改变数据成员,因此应声明为const成员,另外又因为是const成员,所以隐式传入的this指针是const A *类型,返回引用是为了方便链式调用,此时*this是const A 类型,所以返回值是const A &类型,代码如下:
class A {
int i = 0;
public:
const A &print() const {
cout << i<<endl;
cout << "const";
return *this;
}
A & set(int n) {
i = n;
return *this;
}
};
当我们使用如下代码:
int main() {
A a;
a.print().set(7);
}
会发生报错,因为print返回的是const A &类型,而const对象无法调用非const成员函数,也无法修改const对象数据成员。
解决方法是重载print函数
class A {
int i = 0;
public:
const A &print() const {
cout << i<<endl;
cout << "const";
return *this;
}
A &print() {
cout << i << endl;;
cout << "non-const";
return *this;
}
A & set(int n) {
i = n;
return *this;
}
};
const A &是底层const,因此print可以成功重载(顶层const无法重载)。对const版本的print来说,隐式传入的this指针是const A * 类型,而非const版本的print函数隐式传入的是A *类型,根据最佳匹配原则,如果是A类型的对象调用print,将调用非const版本,因为相比const版本,this指针不需要进行类型转换,此时返回值是非常量因此可以调用set函数;如果是const A类型的对象调用print,将调用const版本print,因为const A *无法转换为A *,唯一匹配的是const版本print。
知识点:
1.底层const可以重载,顶层const无法重载
2.成员函数调用时隐式传入this指针,指向调用的对象
3.const对象只能调用const成员函数;const对象的值不能被修改,在const成员函数中修改const对象数据成员的值是语法错误;在const函数中调用非const成员函数是语法错误。