【问题标题】:How to implement two classes for automatic decision over deep and shallow copy?如何实现两个类来自动决定深拷贝和浅拷贝?
【发布时间】:2012-11-12 12:22:59
【问题描述】:

我有以下设计问题:
我有一个带有两种访问器的Resource:

  • 一个是修改它(我们称之为Access)
  • 一个用于类似 const 的访问(我们称之为 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() 仍然有效,我必须手动隐藏非常量访问器。我尝试过受保护或私有继承,但这也限制了Access& 处理Const_Access& 的灵活性。

这个问题的正确解决方案是什么?

【问题讨论】:

  • 由于Const_Access 的合约比Access 的合约窄,因此上述继承没有意义。 Const_Access 不能用来代替 Access,因此这将违反 Liskov 替换原则。
  • 我不认为这是重复的问题,因为违反了 Liskov 替换原则。

标签: c++ polymorphism deep-copy shallow-copy


【解决方案1】:

你说的很矛盾。

一方面,您希望禁止以下内容:

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 时,它唯一没有提供的就是深拷贝。

【讨论】:

  • 是的,这将是正常的解决方案,但正如您所写,它不会在 Access 到 Const_access 上提供深层复制。这就是我在问题中提出一个颠倒的讨厌的东西的原因。 :( 好复杂 :(
【解决方案2】:

您的函数method() 在基类中具有公共可见性,但在派生类中是私有的。这违反了 Liskov 替换原则。派生类应该扩展而不是收缩基类。

解决方案是不违反该原则。例如,将class Const_access 中的继承设为私有或受保护,或者在class Const_access 中提供method() 的实现。

【讨论】:

    【解决方案3】:

    这个问题可以用所谓的惰性求值简单地解决:
    只有在成员函数想要修改它时才对类资源进行私有克隆。通过私有继承可以轻松解决对资源的 R/W 和只读访问。

    这种方式也遵守 LSP:Obj 现在完美地公开继承自 Const_obj,如果有必要的话。
    There is a link for the complete answer.

    【讨论】:

      猜你喜欢
      • 2012-04-12
      • 2015-01-13
      • 1970-01-01
      • 2016-12-03
      • 2012-04-13
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      相关资源
      最近更新 更多