C++的encapsulation机制使得我们可以使得一个类的逻辑接口和内部表示有很大的差异,比如下面这个矩形类:

class Rectangle
{
public:
    int width() const {return x;}
    int height() const {return y;}
    int Area() const {return x * y;}
    int totalLength() const {return 2 * (x + y);}
private:
    int x, y;
};

从逻辑接口上看,我们可以认为这个类有四个状态(width(), height(), Area(), totalLength()),尽管实际上我们并不是这么表示的。

有一点特别需要注意的是,当我们决定一个成员函数是不是const的时候,我们考虑的是它会不会导致逻辑状态的变更。

可以考虑这样一个容器类:

template<typename T>
class CacheVector
{
public:
    T lookup(int i ) const
    {
             assert(i >= 0 && i < size);
             cache = _data[i];
             return _data[i];
    }
private:
    T*  _data;
    size_t _size;
    mutable T cache;
};

这段代码有两点值得关注:为什么lookup方法被设计成const的?mutable起什么作用?

因为lookup并没有改变CacheVector<T>的逻辑状态,尽管我们更新了缓存,但这个对于类的使用者而言是不可见的。

mutable关键字的作用就是在const成员函数里面修改特定成员,事实上也表明这个成员与类的逻辑状态没有关系。