理解常量成员函数

常量成员函数 (const member function), 可读取类中的数据成员,但不能修改

1  声明

1.1  const 关键字  

  参数列表后,加 const 关键字,声明为常量成员函数,表明其不被允许修改类的数据成员

  下面的类,以年、月、日的形式来表示日期 (注意:年月日的声明顺序)

复制代码
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_;  
};
复制代码

  1) 如果常量成员函数,企图修改类的数据成员,则编译器会报错

// error : attempt to change member value in const function
int Date::GetYear() const
{
    return ++y_; 
}

  2) 如果在类外面,“定义” 常量成员函数 ( “定义” = 实现,即 implementation),则 const 关键字不可省略

// error : const missing in member function type
int Date::GetYear() 
{
    return y_;
}

1.2  C++ 陷阱

  类中成员变量的声明顺序,决定了成员变量的初始化顺序。假设 Date 类中的构造函数为:

public:
    Date() : y_(2016), m_(9), d_(22) {}

  此时,类中的成员函数,在类中的声明顺序 = 构造函数初始化列表顺序,故 y_, m_, d_ 都能被顺利的初始化为对应的值。

  而当成员变量,在类中的声明顺序 ≠ 构造函数初始化列表顺序 时,

public:
    Date() : y_(2016), d_(22), m_(d_-13) {}

  根据成员变量的声明顺序,y_ 首先被初始化为 2016,然后再初始化 m_,但由于 d_ 并未被初始化,所以 m_ 的值是随机的,最后初始化 d_ 为 22

  这是因为,类的成员变量在初始化时,其初始化的顺序只与声明顺序有关,而与在初始化列表中的顺序无关。

 

2  调用

  一个常量成员函数,可以被 const 和 non-const 类对象调用; 而非常量成员函数,例如 AddYear(),则只能被 non-const 型类对象调用。

void  Date::AddYear(int n)
{
    y_ += n;  
}

  调用函数如下:

复制代码
void f(Date& d, const Date& cd)
{
    int i = d.GetYear();    // OK
    d.AddYear(1);        // OK

    int j = cd.GetYear();    // OK
    cd.AddYear(1);        // error
}
复制代码

  此时,const 修饰函数形参,是 “接口” 的常用指定形式, 这样 数据 可以传递给 函数 而 本身不被修改

  C++ 中的类型转换 const_cast,可以移除对象的 const 属性,具体使用为: const_cast<T>(expression)

  则上例中,要使 const 型类对象,调用类的 non-const 成员函数,可修改代码如下:

void f(Date& d, const Date& cd)
{
    int j = cd.GetYear();    // OK
    const_cast<Date&>(cd).AddYear(1); 
}

  这种做法虽然是可以的,但它破坏了使用 const 来指定 “接口“ 的本意,并不推荐。


3  解释

  this 指针 默认是指向 non-const 型类对象的 const 型,因此,不能将 this 指针和 const 型类对象绑定,即 const 类对象无法调用类的成员函数

// 默认的 this 指针,指向 non-const 类对象
Date * const this;

   在成员函数声明的参数列表后加 const 后缀,表明其 this 指针指向 const 型类对象,如此, const 型类对象便可以调用常量成员函数了

// 常量成员函数中的 this 指针,指向 const 类对象
const Date * const this;

  

小结:

1) 类成员函数声明中的 const 后缀,表明其 this 指针指向 const 型类对象,因此该 const 类对象,可以调用常量成员函数 (const member function)

2) 一个成员函数,如果对数据成员只涉及读操作,而不进行修改操作,则尽可能声明为常量成员函数


请谨记

1、const成员函数是class中比较特殊的函数。这种函数不能调用非const成员函数。

2、声明const的对象,只能调用const成员函数,而不能调用其他成员函数。

猜你喜欢

转载自blog.csdn.net/u010248077/article/details/80919111
今日推荐