成员函数,在参数列表之后加 const,可声明为 常量成员函数,即该函数对于成员变量,只可读不可写
例如,Date 类中的三个常量成员函数:GetYear()、GetMonth() 和 GetDay()
class Date { public: int GetYear() const { return y; } int GetMonth() const { return m; } int GetDay() const { return d; } void AddYear(int n); // add n years private: int y, m, d; };
当在 GetYear() 中,修改成员变量 y 时,编译会报错
// error : attempt to change member value in const function int Date::GetYear() const { return ++y; }
注意 1):常量成员函数,在类外面实现时,const 后缀不可省略
// error : const missing in member function type int Date::GetYear() { return y; }
注意 2):成员变量前有 mutable,则在常量成员函数中,也可修改成员变量
class Date { // ... private: mutable int y; }; // ok, even changing member value in const function int Date::GetYear() { return ++y; }
const 成员函数,可被 const 或 non-const 型类对象调用,如 GetYear(),而 non-const 成员函数,只能被 non-const 对象调用,如 AddYear()
void func(Date& d, const Date& cd) { int i = d.GetYear(); // OK d.AddYear(1); // OK int j = cd.GetYear(); // OK cd.AddYear(1); // error }
任何成员函数,都有一个隐含的形参,即指向该类对象的 this 指针,它通常由编译器隐式的生成,通过 this 指针,类对象才能调用成员函数
一般的,this 指针默认指向 non-const 对象,因此,const 类对象,无法通过 this 指针调用 non-const 函数
// 默认的 this 指针,指向 non-const 对象 Date * const this;
而 const 成员函数,通过参数后的 const 后缀,修改其 this 指针指向 const 型对象,此时,const 对象便可调用 const 成员函数
// 常量成员函数中的 this 指针,指向 const 对象 const Date * const this;
上文的 func() 函数中,形参用 const 来修饰,可保证数据传递给函数,而本身不被修改,是设计 "接口" 的一种常用形式
void func(Date& d, const Date& cd) { // ... ... }
特殊情况下,想要 const 对象调用 non-const 成员函数,则可用 const_cast 移除对象的 const 属性,具体形式为: const_cast<T>(expression)
void func(Date& d, const Date& cd) { int j = cd.GetYear(); // OK const_cast<Date&>(cd).AddYear(1); // const 对象调用 non-const 成员函数 }
这种做法,破坏了用 const 来指定 "接口" 的本意,并不推荐
《C++ Programming Language》4th ch 16.2.9.1
《C++ Primer》5th ch 7.1.2
《Effective C++》3rd Item 3, item 27
《More Effective C++》 Item 2