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成员函数里面修改特定成员,事实上也表明这个成员与类的逻辑状态没有关系。