【问题标题】:c++ clone function in abstract classc++ 抽象类中的克隆函数
【发布时间】:2015-02-02 08:37:49
【问题描述】:

在 c++11 标准中,如果 B 类继承自 A 类,则“B 是 A”。 但是,我仍然对这个概念感到困惑: 看看这段代码:

class Base {
public: 
    virtual ~Base() {}
    virtual Base* clone() const = 0;
};

class Derived : public Base {
public:
    virtual Base* clone() const {
        return new Derived(*this);
    }
    //<more functions>
};

我们从 Derived 返回了一个指向 Base 的指针,但是如果在这段代码中使用这种方法:

Derived* d1 = new Derived();
Derived* d2 = d1->clone();

我们所做的是在Derived* 中分配Base*!!

问题
为什么这段代码不能编译?如何修改它(为什么?)以适应继承?

【问题讨论】:

  • 您发布的代码无法编译。请发布工作代码。特别是如果您的问题是“这段代码是如何编译的?”。
  • 即使我写 Derived d1; 而不是 Derived d1 = new Derived(); 它也不会编译。在 VS 2013 中,我在声明 d2 的行中收到预期的错误消息“无法从 'Base *' 转换为 'Derived *'”。
  • 我猜你的意思是在派生类中返回Derived*类型,这叫做covariance
  • 感谢您的关注。我修改了这个问题,希望它会更清楚,因为我希望它根据我所询问的继承标准和条件进行编译。

标签: c++ c++11 inheritance clone


【解决方案1】:

即使经过一些微不足道的编辑(我所做的),您发布的代码也不会编译。 Derived::clone() 的签名应该是:

virtual Derived* clone() const override {  // <-- return type
  return new Derived(*this);
}

尽管clone()BaseDerived 类中的返回类型不同,但它是virtual 函数的有效覆盖,因为co-variance 在C++ 中是合法的。

当您处理问题中所述的指针时,不会有任何切片。
Derived::clone() 应该返回Derived*

clone() 是否应该是 virtual 取决于设计,但使用 virtual 析构函数是个好主意。


另一种方法是使用template 并避免使用virtual

class Base {
public: 
    virtual ~Base() {}
    template<class T>  // now need not add this trivial code in all derived classes
    T* clone() const { return new T(*this); }
};

【讨论】:

  • 回答了我的问题。我的鞍点是协方差问题和切片问题。 **我仍然是 C++ 的新手,所以请原谅我的原始问题,因为很难找到该语言的可靠来源。
  • @ThunderWiring,还要注意签名中的(关键字)字override (-std=c++11)。如果virtual 方法签名与其基类中的任何方法都不匹配,则会生成错误。
  • 感谢您富有洞察力的回答!我想知道,有没有办法实现一次 clone(),因为它本质上是在所有派生类中复制的?
  • @YuriFeldman,使用模板查看更新后的答案。在这种情况下,我们不必通过添加样板代码来一次又一次地实现相同的方法。
  • 非虚拟和模板克隆的想法毫无意义。如果你有一个 Derived 对象/指针/引用,并且你知道它确实是一个 Derived,只需使用它的复制 ctor 来复制它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 2010-12-12
相关资源
最近更新 更多