本节书摘来自异步社区出版社《C++面向对象高效编程(第2版)》一书中的第3章,第3.6节,作者: 【美】Kayshav Dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。
3.6 const 成员函数的概念
C++面向对象高效编程(第2版)
TIntStack类中的HowMany成员函数有特别的签名:
unsigned HowMany() const;
如第2章所述,const
后缀表明HowMany
是const
成员函数。这意味着,HowMany
不会修改它的调用对象。换言之,HowMany
不会对该对象(即调用HowMany
函数的对象)的任何数据成员赋值。这样的限制由编译器强制执行。以下为该函数的实现:
unsigned TIntStack::HowMany() const
{
// 如果添加_sp = 0; 语句会怎样(仅举个例子)
// _sp = 0;
return _count;
}```
hand 注意,要同时在成员函数的声明和定义中指明const限定符。
上面的代码不会修改对象内的任何数据。它只是读取数据成员_count的值。我们可以将const成员函数看成只读函数。如果在调用const成员函数之前先查看对象中的数据,然后在const成员函数返回后再次检查相同对象中的数据,会发现两组值无任何差别。因为调用的函数是const成员函数,所以对象中的数据都不会被更改1。
如果上面带注释的代码行取消注释,编译器就会发现给成员函数_sp赋值的行为,并立即将其作为错误进行标记,因为我们违反了成员函数的常量性(`constantness`)(即在`cons`成员函数内改变数据成员)。
`const`成员函数到底有什么优点?回顾一下第2章中,关于接口和客户的讨论。`const`成员函数向它的客户保证它运行良好,并告诉客户调用`const`成员函数没有危险。这将逐渐建立客户的自信,他们对正在使用的软件会更加有信心。
在以上的讨论中,我们所见的就是逐位常量性(`bitwise constantness`)或位模式2常量性(`bit-pattern constantness`)的概念。`const`成员函数不会修改对象中的单一位。对象中的位模式在调用const成员函数前后都一样。编译器只是强制执行这种位模式常量性。
思考:
然而有些实例,当成员函数修改对象内部的数据时,从客户的角度看,并不会影响对象。换言之,尽管对象内部的成员函数发生了变化,在客户看来,对象并未改变。这样的成员函数称为强制执行概念上的常量性(或虚常量性`(virtual constantness)`)。即使对象内部的某些位已发生变化,但该对象仍然保留概念上的常量性。我们将在第4章中介绍相关示例。编译器不会强制执行概念上的常量性——这必须由实现者来完成。我们想给客户传达`const`成员函数的视图,与此同时,改变对象内部的一些数据。要让客户信服此函数为`const`成员函数很容易,但如何在`const`成员函数内部改变对象中的数据?编译器会捕捉到这个错误!如果必须在`const`成员函数内部修改某些数据,正确的处理方法是:声明这些数据成员时添加前缀`mutable`限定符(例如,`mutable boo`l `_cacheValid`)。这样,即使在const成员函数中,也可以修改`_cacheValid。
`
1前提是,实现者遵守逐位常量性(`bitwise constantness`)原则,而不是概念上(或逻辑上)的常量性。
2译者注:`bit-pattern`译作“位模式”,指的是在内存中储存的二进制序列。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。