巧用 mutable

 

使用可变(mutable)成员隐藏实现细节

    关键字 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
        }

可变(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<>

本文作者 Danny Kalev 是一位系统分析员、软件工程师,他具有14年在 C++ 和面向对象设计方面的经验。

你可能感兴趣的:(function,image,活动,Class,buffer,disk)