C++ 之 常量成员函数

1  const 后缀    

    成员函数,在参数列表之后加 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;
}  

   

2  this 指针

    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;

  

3  const 接口

   上文的 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