我有以下设计问题:
我有一个Resource
有两种访问器:
Access
)Const_access
),但你可以说c1 = c2然后c1将访问c2。鉴于Resource
很大,我必须实现以下复制机制:
Access->Access: deep copy
Access->Const_access: deep copy
Const_access->Access: deep copy
Const_access->Const_access: shallow copy
我的目标是撰写Access
,以便Const_access
能够完全使用const
中的Access
函数。
我目前的实施存在缺陷,使用:
class Access {
public:
Access(const Access&); // deep copy
void method(const Access&);
void const_method() const;
protected:
Resource res;
};
class Const_access : public Access{
private:
void method(); // only declaration
public:
Const_access(const Const_accesss&); // shallow copy
explicit Const_access(const Access&); // deep copy
};
但是这里Const_access ca; ca.Access::method()
仍然有效,我必须手动隐藏非const访问器。我尝试过保护或私有继承,但这也禁止Access&
处理Const_Access&
的灵活性。
这个问题的正确解决方案是什么?
答案 0 :(得分:2)
你所说的是矛盾的。
一方面,你想要不允许这样的事情:
Const_access foo;
foo.modify();
但另一方面,你确实想要允许这样的事情:
void bar(Access& a) {
a.modify();
}
Const_access foo;
bar(foo);
这没有意义。
更合乎逻辑的关系是围绕继承结构:
class Const_access {
public:
Const_access(const Const_access&); // shallow copy
void const_method() const;
protected:
Resource res; // or perhaps a reference-counted pointer?
};
class Access: public Const_access {
public:
Access(const Access&); // deep copy
explicit Access(const Const_access&); // deep copy
void method();
};
在将Access
转换为Const_access
时,唯一没有给出的是深层复制。
答案 1 :(得分:0)
您的函数method()
在基类中具有公共可见性,但在派生类中是私有的。这违反了Liskov替代原则。派生类应该扩展而不是收缩基类。
解决方案是不违反该原则。例如,将class Const_access
中的继承设为私有或受保护,或在method()
中提供实施class Const_access
。
答案 2 :(得分:0)
这个问题可以通过所谓的懒惰评估简单地解决:
仅当成员函数想要修改它时才创建类资源的私有克隆。通过私有继承可以轻松解决R / W和对资源的只读访问。
这样也可以遵守LSP:Obj
现在可以完全公开地继承Const_obj
,如果有必要的话。
There is a link for the complete answer.