关于c ++:如何在纯抽象类中实现克隆?

How to implement clone in a pure abstract class?

因此,我想在派生类中重写纯抽象方法,但出现此错误。 有人可以帮我看看发生了什么,如何完成。

我的Device类;

1
2
3
4
5
6
7
8
class Device  {
public:
    Device();
    Device(const Device& orig);
    virtual ~Device();

    virtual Device Clone() = 0;
}

还有我的派生类;

1
2
3
4
5
6
7
8
class Radar : public Device {
public:
    Radar();
//    Radar(const Radar& orig); // commenting so the compiler using its default copy constructor
    virtual ~Radar();

    Radar Clone();    
};

我的Radar类的源文件;

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

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

如果使用void类型(我假设它不是我想要的类型),它将表明我尚未实现此方法。

我该怎么办?


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

因此,应为:

1
virtual Device* Clone() = 0;

...然后...

1
2
3
4
5
6
7
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);
}

更新-根据要求提供进一步说明

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

希望这有助于澄清问题。您可能还需要对面向对象编程进行一些背景阅读。


实现此克隆技术的经典方法是对Clone()方法使用协变返回类型。结合现代RAII技术(例如unique_ptr等),它提供了非常灵活和安全的组合,可以适当地管理和克隆对象。

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

建议在原始画笔上使用诸如unique_ptr之类的智能指针,以避免内存泄漏。 clone_unique工厂以标准库中相应的make_unique实用程序为模型,并返回unique_ptr。它包含对参数和目标类型的类层次结构的显式类型检查。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#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);
}

样例代码。

有关更长的示例,请参见此相关答案。


请尝试以下签名

虚拟设备&Clone()= 0;
要么
虚拟设备* Clone()= 0;

//身体

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