简体   繁体   English

C++:深度复制基类指针

[英]C++: Deep copying a Base class pointer

I searched around and seems in order to perform this I need to change my Base class and want to know if this is the best approach.我四处搜索,似乎为了执行此操作,我需要更改我的 Base 类,并想知道这是否是最佳方法。 For example, I have a Base class:例如,我有一个基类:

class Base {}

Then a long line of derived classes:然后是一长串派生类:

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

And then I have another class:然后我还有另一堂课:

class DeepCopy 
{ 
  Base * basePtr;

  public:
   DeepCopy(DeepCopy & dc) {}
}

Assuming the Base class and Derived_x class copy constructors are properly coded, what is the best way to write the copy constructor for DeepCopy.假设 Base 类和 Derived_x 类复制构造函数被正确编码,那么为 DeepCopy 编写复制构造函数的最佳方法是什么。 How can we know about the class that is in the basePtr of the object we are going to copy?我们如何知道我们要复制的对象的 basePtr 中的类?

Only way I can think of is using RTTI, but using a long list of dynamic_casts seems not right.我能想到的唯一方法是使用 RTTI,但使用一长串 dynamic_casts 似乎不对。 Besides it requires DeepCopy to know about the inheritance hierarchy of Base class.此外,它需要 DeepCopy 了解 Base 类的继承层次结构。

The other method I saw is here .我看到的另一种方法是here But it requires Base and Derived classes implement a clone method.但它需要 Base 和 Derived 类实现克隆方法。

So is there a much easier, standard way of doing this?那么有没有更简单的标准方法来做到这一点?

You need to use the virtual copy pattern: provide a virtual function in the interface that does the copy and then implement it across the hierarchy:您需要使用虚拟复制模式:在执行复制的接口中提供一个虚拟函数,然后跨层次结构实现它:

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);
   }
};

Then the DeepCopy object just needs to call that function:然后DeepCopy对象只需要调用该函数:

class DeepCopy 
{ 
  Base * basePtr;    
public:
   DeepCopy(DeepCopy const & dc)           // This should be `const`
      : basePtr( dc.basePtr->clone() )
   {}
};

Using an approach that employs a clone() function is a good solution.使用采用clone()函数的方法是一个很好的解决方案。 Note using the CRTP (the curiously recurring template pattern) can save you some of the work .注意使用CRTP(奇怪的重复模板模式)可以为您节省一些工作 The way you do it is by introducing an intermediate level (called BaseCRTP below) which is a template and implements the clone() function.你这样做的方法是引入一个中间级别(下面称为BaseCRTP ),它是一个模板并实现了clone()函数。 When you derive your actual classes, use them as the template argument of the base they are derived from.当您派生实际类时,将它们用作它们派生自的基类的模板参数。 They will get the clone() function implemented for them automatically.他们将自动为他们实现clone()函数。 Make sure the derived classes implement a copy constructor (or be sure the default is what you need).确保派生类实现了复制构造函数(或确保默认值是您需要的)。

/* 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... */
};

You can then obviously implement the DeepCopy class in the usual way:然后,您显然可以以通常的方式实现DeepCopy类:

class DeepCopy 
{ 
  Base *basePtr;    
public:
  DeepCopy(const DeepCopy &dc)
    : basePtr(dc.basePtr->clone())
  {}
};

I think that templates are the best way to go in this situation:我认为在这种情况下模板是最好的方法:

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

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

This does mean that DeepCopy 's are un-assignable to each other, but that's the price you pay with C++.这确实意味着DeepCopy不可相互分配,但这是您使用 C++ 付出的代价。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM