class CTextBlock {
public:
...
char& operator[](std::size_t position) const // operator[] 不恰当的 (但是符合按位恒定规则)定义方法
{ return pText[position]; }
private:
char *pText;
};
尽管 operator[] 返回一个对对象内部数据的引用,这个类仍(不恰当地)将其声明为 const 的 成员函数(第 28 项将深入讨论这个问题)。先忽略这个问题,请注意 operator[] 的实现中并没有以任何形式修改 pText 。于是编译器便会欣然接受这样的做法,毕竟,所有的编译器所检查的是“代码是否符合按位恒定规则”。但是请观察,在编译器的纵容下,还会有什么样的事情发生:
const CTextBlock cctb("Hello");// 声明对象常量
char *pc = &cctb[0]; // 调用 const 的 operator[],从而得到一个指向 cctb 中数据的指针
*pc = 'J'; // cctb 现在的值为 "Jello"
当你创建了一个包含具体值的对象常量后,你仅仅通过对其调用 const 的成员函数,就可以改变它的值!这显然是有问题的。

辑恒定应运而生。坚持这一宗旨的人们争论道,一个 const 的成员函数可能对其调用的对象内部做出改动,但是仅仅以客户端无法察觉的方式进行。比如说,你的 CTextBlock 类可能需要保存文字块的长度,以便在需要的时候调用:
class CTextBlock {
public:
...
std::size_t length() const;
private:
char *pText;
std::size_t textLength; // 最后一次计算出的文字块长度
bool lengthIsValid; // 当前长度是否可用
};
std::size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText); // 错误!不能在 const 成员函数中
lengthIsValid = true; // 对 textLength 和 lengthIsValid 赋值
}
return textLength;
}
以上 length 的实现绝不是按位恒定的。这是因为 textLength 和 lengthIsValid 都可以改动。尽管看上去它应该对于 CTextBlock 对象常量可用,但是编译器不答应。编译器始终坚持遵守按位恒定。那么该怎么办呢?
解决方法很简单:利用 C++ 中 与 const 相关的灵活性,使用可变的( mutable )数据成员。 mutable 可以使非静态数据成员不受按位恒定规则的约束:
class CTextBlock {
public:
...
std::size_t length() const;
private:
char *pText;
mutable std::size_t textLength;// 这些数据成员在任何情况下均可修改
mutable bool lengthIsValid; // 在 const 成员函数中也可以
};
std::size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText); // 现在可以修改了
lengthIsValid = true; // 同上
}
return textLength;
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-62399-4.html
好暖心哈哈哈哈
全世界能单挑赢的船应该不超过10艘
俺们那的人大部分谈生意都很实诚