如何在纯抽象类中实现clone?

时间:2014-10-21 06:09:04

标签: c++ abstract derived-class

所以我想在派生类中覆盖纯抽象方法,但是我得到了这个错误。有人可以帮助我看看发生了什么,我怎样才能完成它。

我的Device课程;

class Device  {
public:
    Device();
    Device(const Device& orig);
    virtual ~Device();

    virtual Device Clone() = 0;
}

我的派生类;

class Radar : public Device {
public:
    Radar();
//    Radar(const Radar& orig); // commenting so the compiler using its default copy constructor
    virtual ~Radar();

    Radar Clone();    
};

我的Radar类的源文件;

Radar Radar::Clone() {
    return *(new Radar(*this));
}

如果我在Device类的Clone方法中使用Device类型,则会弹出Device是抽象类。

如果我使用void类型(我假设它不是我想要的),则会显示我没有实现此方法。

我该怎么办?

3 个答案:

答案 0 :(得分:3)

您的Clone方法需要返回指向克隆对象的指针...协变返回类型只能以这种方式工作(因为返回值要求调用者将返回的值复制到堆栈中 - 这将是当您使用new)分配内存泄漏时。

所以,它应该是:

virtual Device* Clone() = 0;

......以后......

Radar* Clone();    // YES, it should be Radar* here - that uses C++'s support for
                   // "covariant return types", see also "UPDATE" discussion

Radar* Radar::Clone()
{
    return new Radar(*this);
}

更新 - 按要求进一步解释

因此,使用克隆函数的想法是它可以返回您Device*当前正在寻址的任何实际派生类型的深层副本。鉴于派生类型可能会添加Device缺少的数据成员,它可能是一个更大的对象,并且调用者无法保留适当的堆栈空间来存储它。因此,需要使用new动态分配对象,并且可预测大小的Device*是调用者访问新对象的方式。克隆函数返回Radar*是合法的 - 这意味着客户端代码在编译时知道它正在处理Radar并且克隆它可以继续使用它作为Radar - 访问Radar提供的任何额外成员。

希望有助于澄清事情。您可能还想对面向对象的编程进行一些背景阅读。

答案 1 :(得分:1)

实施此cloning technique的经典方法是将covariant return types用于Clone()方法。结合现代RAII技术(例如unique_ptr等),它提供了一种非常灵活和安全的组合,可以适当地管理和克隆对象。

协变返回类型的一个优点是,您可以获取克隆对象(深层副本),并且返回类型与层次结构中相同的级别作为参数 (即返回并不总是基类)并且不需要立即转换。在C ++中,指针和引用支持协方差,值不支持协方差。

建议对原始画家使用智能指针(如unique_ptr )以避免内存泄漏。 clone_unique工厂是根据标准库中相应的make_unique工具建模的,并返回unique_ptr。它包含对参数和目标类型的类层次结构的显式类型检查。

该解决方案确实需要使用std::unique_ptr。如果您的编译器不可用,boost会为这些提供替代方案。还有一些其他较新的C ++语言功能,但如果需要,可以删除它们。

#include <type_traits>
#include <utility>
#include <memory>

class Device {
public:
  virtual Device* Clone() const = 0;
};

class Radar : public Device {
public:
  virtual Radar* Clone() const override {
    //    ^^^^^^ covariant return compared to Device::Clone
    return new Radar(*this);
  }
};

// Clone factory

template <typename Class, typename T>
std::unique_ptr<Class> clone_unique(T&& source)
{
  static_assert(std::is_base_of<Class, typename std::decay<decltype(*source)>::type>::value,
    "can only clone for pointers to the target type (or base thereof)");
  return std::unique_ptr<Class>(source->Clone());
}

int main()
{
  std::unique_ptr<Radar> radar(new Radar());
  std::unique_ptr<Device> cloned = clone_unique<Device>(radar);
}

Sample code

See this related answer更长的例子。

答案 2 :(得分:-1)

请尝试以下签名

虚拟设备&amp;克隆()= 0; 要么 虚拟设备*克隆()= 0;

//体

Device&  Radar::Clone() {
    return  Radar(*this));
}