27

我四处搜索,似乎为了执行此操作,我需要更改我的 Base 类并想知道这是否是最好的方法。例如,我有一个基类:

class Base {}

然后是一长串派生类:

class Derived_1:: public Base {}
class Derived_2:: public Derived_1{}
...
...
class Derived_n:: public Derived_M{}

然后我有另一堂课:

class DeepCopy 
{ 
  Base * basePtr;

  public:
   DeepCopy(DeepCopy & dc) {}
}

假设 Base 类和 Derived_x 类的复制构造函数编码正确,那么为 DeepCopy 编写复制构造函数的最佳方法是什么。我们如何知道要复制的对象的 basePtr 中的类?

我能想到的唯一方法是使用 RTTI,但使用一长串 dynamic_casts 似乎不正确。此外,它需要 DeepCopy 了解 Base 类的继承层次结构。

我看到的另一种方法是here。但它需要 Base 和 Derived 类实现克隆方法。

那么有没有更简单、更标准的方法呢?

4

3 回答 3

32

您需要使用虚拟复制模式:在执行复制的接口中提供一个虚拟函数,然后在整个层次结构中实现它:

struct base {
   virtual ~base() {}                // Remember to provide a virtual destructor
   virtual base* clone() const = 0;
};
struct derived : base {
   virtual derived* clone() const {
      return new derived(*this);
   }
};

然后DeepCopy对象只需要调用该函数:

class DeepCopy 
{ 
  Base * basePtr;    
public:
   DeepCopy(DeepCopy const & dc)           // This should be `const`
      : basePtr( dc.basePtr->clone() )
   {}
};
于 2012-09-04T01:00:18.557 回答
24

使用采用clone()函数的方法是一个很好的解决方案。注意使用CRTP(奇怪的重复模板模式)可以为您节省一些工作。你这样做的方法是引入一个中间级别(BaseCRTP下面称为),它是一个模板并实现了该clone()功能。当您派生实际类时,将它们用作派生它们的基类的模板参数。他们将clone()自动获得为他们实现的功能。确保派生类实现复制构造函数(或确保默认值是您需要的)。

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

/* Intermediate class that implements CRTP. Use this
 * as a base class for any derived class that you want
 * to have a clone function.
 */
template <typename Derived>
class BaseCRTP : public Base {
public:
  virtual Base *clone() const {
      return new Derived(static_cast<Derived const&>(*this));
  }
};

/* Derive further classes. Each of them must
 * implement a correct copy constructor, because
 * that is used by the clone() function automatically.
 */
class Derived1 : public BaseCRTP<Derived1> {
  /*... should have an ordinary copy constructor... */
};

class Derived2 : public BaseCRTP<Derived2> {
  /*... should have an ordinary copy constructor... */
};

然后,您显然可以DeepCopy以通常的方式实现该类:

class DeepCopy 
{ 
  Base *basePtr;    
public:
  DeepCopy(const DeepCopy &dc)
    : basePtr(dc.basePtr->clone())
  {}
};
于 2012-09-04T01:11:58.327 回答
1

我认为模板是在这种情况下最好的方法:

template<typename Sub>
class DeepCopy
{
    Base *base;

    DeepCopy(Sub *sub)
    {
        base = new Sub(*sub); // use copy constructor
    }
}

这确实意味着DeepCopy' 不能相互分配,但这就是您使用 C++ 所付出的代价。

于 2012-09-04T01:00:45.367 回答