在派生类的基类具有成员指针时深层复制派生类

问题描述 投票:0回答:1

我正在尝试制作类d的对象Derived的深层副本,如下面的代码所示:

class A {
public:
   int m_int;
   A* clone() {
      return new A(*this);
   }
};

class Base {
public:
   A* m_a;
   virtual Base* clone() {
      A* new_a = new A();
      new_a = this->m_a->clone();
      Base* clone = new Base(*this);
      clone->m_a = new_a;
      return clone;
   }
};

class Derived : public Base {
public:
   double m_dbl;
   virtual Derived* clone() {
      return new Derived(*this);
   }
};

int main() {
   Derived* d = new Derived();
   d->m_dbl = 1.234;

   A* a = new A();
   a->m_int = -1;

   d->m_a = a;

   //clone d
   Derived d_copy = d->clone();

   //changing values of d's attributes must not affect d_copy
   a->m_int = 10;
   d->m_dbl = 3.456;

   //check d_copy
   cout << "m_int " << d_copy->m_a->m_int << endl;
   cout << "m_dbl " << d_copy->m_dbl << endl;
}

输出:

m_int 10 //wrong, should be -1;
m_dbl 1.234 //correct

正如你所看到的,简单地在Derived的new Derived(*this)方法中返回clone()是错误的,因为它不会深层复制m_a

如果我“摧毁”m_aBaseDerived的深刻复制,那么我将得到正确答案:

   virtual Base* clone() = 0;

   ...

   virtual Derived* clone() {
      A* new_a = new A();
      new_a = this->m_a->clone();
      Derived* clone = new Derived(*this);
      clone->m_a = new_a;    
      return new Derived(*this);
   }
   //gives out m_int = -1

如果是这种情况,这是否意味着每次我从Derived创建更多的派生类时,我总是要“降低”clone()的内容给他们?

此外,如果例如Base有两个派生类Derived1Derived2,这是否意味着我必须深深复制Base的成员?

任何其他方法来解决这个问题?

c++ inheritance deep-copy
1个回答
0
投票

您可以考虑实现始终执行深层复制的复制构造函数。在这种情况下,你的clone实现将始终是微不足道的:

class Base {
public:
   A* m_a;
   Base(const A& other)
       : m_a(other.m_a->clone())
   {       
   }

   virtual Base* clone() {
      return new A(*this);
   }
};

class Derived : public Base {
public:
   double m_dbl;
   Derived(const Derived& other)
       : m_dbl(other.m_dbl)

   virtual Derived* clone() {
      return new Derived(*this);
   }
};

如果您不想更改默认构造函数的行为(例如,您希望默认构造函数生成浅层复制),则可以选择将复制实现移动到CopyTo方法,以便重用它:

class Base {
public:
   A* m_a;
   static void CopyTo(const Base& from, Base& to)
   {
        to.m_a = from.m_a->clone();
   }

   virtual Base* clone() {
      Base* result = new Base();
      CopyTo(*this, result);

      return result;
   }
};

class Derived : public Base {
public:
   double m_dbl;

   static void CopyTo(const Base& from, Base& to)
   {
        Base::CopyTo(from, to);
        to.m_dbl= from.m_dbl;
   }

   virtual Derived * clone() {
      Derived * result = new Derived ();
      CopyTo(*this, result);

      return result;
   }

   virtual Derived* clone() {
      return new Derived(*this);
   }
};
© www.soinside.com 2019 - 2024. All rights reserved.