簡體   English   中英

在派生類的基類具有成員指針時深層復制派生類

[英]Deep-copying a derived class when its base class has member pointers

我正在嘗試制作類Derived的對象d的深層副本,如下面的代碼所示:

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的clone()方法中返回new Derived(*this)是錯誤的,因為它不會深層復制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成員?

任何其他方法來解決這個問題?

您可以考慮實現始終執行深層復制的復制構造函數。 在這種情況下,您的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);
   }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM