在阅读Scott Meyers的 Effective C++ 之后,以下是一个解决方案:
定义一个执行惰性评估的模板(使用引用计数):
class Obj : private lazy<Obj_data>{};
并且惰性存储 Obj_data 私有,具有受保护的访问器,一个用于修改,一个用于只读访问。
如果需要,修饰符访问器首先对数据进行深度复制Obj_data
,然后移交对数据的引用。只读访问器只返回一个 const 引用。
这样做的总成本是存储 2 个额外的指针(一个用于数据,一个用于计数器)和一个计数器。
实现是这样的:
class lazy{
protected:
lazy(const lazy&obj){lazy_copy(obj);}
//(the required constructors, operator= ...)
// accessors:
const Obj_data& data() const {return *od;}
Obj_data& mod_data() {make_private(); return *od;}
private:
void lazy_copy(const lazy& obj);
void make_private(); // this does the actual deep-copy, as late as possible.
private:
counter*;
Obj_data* od;
};
因此,读取和修改 gos 的Obj
属性
void Obj::method(){
cout << data().some_attribute; // simple read
mod_data().i = 10; // simple modify
const Obj_data& const_d = data(); // assignable for lots of read-outs
Obj_data& var_d = mod_data(); // assignable for lots of modifications.
}
请注意,您只能data()
将const
成员用作mod_data()
类中的非常量函数,因此此解决方案是完全安全的,开销很小。
理论背景:问题中期望的行为是一个实现细节,与客户端无关。因此我们通过私有继承来解决它。