C++: Deep copying a Base class pointer

前端 未结 3 2036
清酒与你
清酒与你 2020-12-02 11:51

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. For example, I have a Base class:

相关标签:
3条回答
  • 2020-12-02 12:02

    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++.

    0 讨论(0)
  • 2020-12-02 12:12

    Using an approach that employs a clone() function is a good solution. Note using the CRTP (the curiously recurring template pattern) can save you some of the work. The way you do it is by introducing an intermediate level (called BaseCRTP below) which is a template and implements the clone() function. 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. 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:

    class DeepCopy 
    { 
      Base *basePtr;    
    public:
      DeepCopy(const DeepCopy &dc)
        : basePtr(dc.basePtr->clone())
      {}
    };
    
    0 讨论(0)
  • 2020-12-02 12:22

    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:

    class DeepCopy 
    { 
      Base * basePtr;    
    public:
       DeepCopy(DeepCopy const & dc)           // This should be `const`
          : basePtr( dc.basePtr->clone() )
       {}
    };
    
    0 讨论(0)
提交回复
热议问题