C++ 常量成员函数

文章目录

  • 1 声明
    • 1.1 const 关键字
    • 1.2 C++ 陷阱
  • 2 调用
  • 3 解释
  • 小结:


常量成员函数 (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_; 
}
  1. 如果在类外面,“定义” 常量成员函数 ( “定义” = 实现,即 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(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. 一个成员函数,如果对数据成员只涉及读操作,而不进行修改操作,则尽可能声明为常量成员函数

你可能感兴趣的:(C/C++,C++,常量成员函数)