C++pimer中文版第四版 378页 基于const的重载
如果我们要在一个类的成员函数中定义两个函数签名完全一样的成员函数,比如display,那么可以基于是否是const成员函数来重载。比如:
//非const对象可以使用可以使用任意成员,但是下面这个匹配的更好,所以一般用这个成员函数 Screen& display(ostream& os){ os << "something"; return *this;//返回的是普通引用 Screen&, this类型为Screen* const } //const对象只能使用下面这个const成员函数 const Screen& display(ostream& os) const{ os << "something"; return *this;//返回到额是const引用 const Screen&, this类型为const Screen* const }
注意上面代码中的this指针的类型:在普通的非const成员函数中,this的类型是一个指向类类型对象的const指针,Screen* const,可以改变this所指向的值,但不能改变this所保存的地址(this的地址就是调用该函数的对象的地址,当然无法改变)。而在const成员函数中,this的类型是一个指向类类型const对象的const指针,const Screen* const,所以既不能改变this所指向对象的值,也不能改变this本身所保存的值(这点是肯定的,刚刚说过)。
由于const成员函数之所以定义成const类型,就是不想改变类对象,所以const成员函数如果返回引用类型(当然,返回非引用类型肯定没问题),只能返回const引用类型,可以返回指向类对象的引用*this,也可以返回指向成员属性的引用(这种情况在《深入探索C++对象模型》第一章有例子)。
《深入探索C++对象模型》第一章 第4页
这个例子中也存在基于成员函数是否是const的重载,两个函数签名相同的成员函数operator[]是重载关系,非const对象调用第一个成员函数,const调用第二个成员函数。
如下:
#include <iostream> #include <cassert> using namespace std; template <class type, int dim> class Point{ public: Point(){}; Point(type coords[dim]){ for(int index = 0; index < dim; ++index){ _coords[index] = coords[index]; } } //基于成员函数是否是const可以重载成员函数 type& operator[](int index){ assert(index < dim && index >= 0); cout << "ordinary fun." << endl; return _coords[index]; } const type& operator[](int index) const{ assert(index < dim && index >= 0); cout << "const fun." << endl; return _coords[index]; } private: type _coords[dim]; }; template <class type, int dim> ostream& operator<<(ostream& os, const Point<type, dim>& pt){ os << "("; for(int i = 0; i < dim - 1; ++i) os << pt[i] << ","; os << pt[dim - 1]; os << ")"; return os; } int main() { int a[] = {1, 2, 3}; Point<int, 3> point1 = Point<int, 3>(a); cout << point1 << endl; cout << point1[0] << endl; point1[0] = 100; cout << point1[0] << endl; return 0; }