【转】http://www.builder.com.cn/2004/0531/119655.shtmlhttp://www.ieee.org.cn/dispbbs.asp?boardID=61&ID=43781关键字 mutable 是一个奇怪的修饰符(specifier),它只能够用于一个类的非静态数据成员。下面我将讨论 mutable 的语义和用法,但是首先我要解释一下 C++ 对象模型的一个关键概念
对象的状态
一个对象的状态由其非静态数据成员的值构成,因此,修改一个数据成员将会改变整个对象的状态。将一个成员函数声明为 const 能够保证它不会改变对象的状态。
然而在一些情况下,对象的逻辑状态与基物理状态之间可能有差别。例如,对于一个表示绘画图像的对象就存在这种情况。如果图像还没有更改,那么我们就认为其状态没有发生变化。然而,从底层实现方面来说,如果大对象在一段时间没有活动,那么它们的内存通常会被交换到一个文件中。交换一个图像并不会真地影响其状态,但是对象的一些数据成员可能会发生变化,在这里可能会发生变化的是指针、标志位等。
在用户调用一个诸如 Redraw() 之类的 const 成员函数时,他们并不关心这个函数在内部是如何实现的。从他们的角度来说,这个函数并不改变对象的逻辑状态,因此被声明为 const。Redraw() 有可能修改对象的物理状态这一事实是一个他们不应该关心的实现细节。例如:
int Image::Redraw() const
{
if (isLoaded==false)
{
//..read image data from a disk into a local buffer
isLoaded=true; //changing a data member's value
}
//..paint image in the screen
}
class Image
可变(mutable)数据成员
如果尝试编译这段代码,你会得到一个编译错误。虽然 Redraw() 声明为 const,但是它修改了一个数据成员。解决这个编译错误的方法是将 isLoaded 声明为一个 mutable 数据成员:
class Image
{
public:
int Redraw() const;
//..
private:
mutable bool isLoaded;//can be changed by a const function
};
不像普通的数据成员,const 成员函数可以修改 mutable 数据成员。
Mutable 数据成员的使用看上去像是骗术,因为它能够使 const 函数修改对象的数据成员。然而,明智地使用 mutable 关键字可以提高代码质量,因为它能够让你向用户隐藏实现细节,而无须使用不确定的东西,比如 const_cast<>。
具体一些的例子:
mutable的作用是用来修饰类的成员变量,使这个成员变量的值在任何情况下都可以被修改,例如:
为叙述方便,预定义一个类TObject,如下:
class TObject
{
int iValue;
};
情况1:
我们知道,若TObject中存在一个成员函数,并且次函数的声明末尾加上了const关键字,形式如下:
void setValue(int) const; // 注:有些地方把这种函数称为常函数。
那么这就意味着,这个函数的实现中不能修改该类的成员变量的值,但是,倘若我们要记录这个函数调用的次数,我们会有很多方法,如间接调用该函数,但是这显然不是一个好方法,这会增加类的复杂度。这个时候mutable就派上用场了,它可以使被修饰的成员变量在该种情况下被改变,你可以这样书写代码:
class TObject
{
mutable int iValue;
public:
void setValue(int pValue) const
{
iValue++;
}
};
当然,这并不是一个好例子,因为它没有多少实用价值,我的目的在于说明问题。
情况2:
若有一个TObject的实例被定义为常量,如:
const TObject tObject; // 注:有些地方将之称为常对象。
如果没有mutable的话,这显然意味着你将无法修改该对象,那么,如果你只希望关闭掉部分成员变量的修改权,那么你就应该像情况1那么书写代码,让你调用setValue成员函数时仍能修改iValue的值。