Конструктор виртуальной копии и метод клонирования

#c #clone

#c #клонирование

Вопрос:

Я был на теме «конструктор виртуальной копии» в своей книге. В абзаце говорится

Конструкторы не могут быть виртуальными, и поэтому технически не существует такой вещи, как конструктор виртуальной копии. Тем не менее, иногда вашей программе отчаянно необходимо иметь возможность передавать указатель на базовый объект и иметь копию правильного созданного производного объекта. Общее решение этой проблемы — создать метод Clone() в базовом классе и сделать его виртуальным. Метод Clone() создает новую копию объекта текущего класса и возвращает этот объект.

И затем книга дала следующий код (я удалил некоторую его часть, которая не была необходимой, связанной с моими сомнениями).

 #include <iostream>
 using namespace std;
 class Mammal
{
 public:
  Mammal() {}
  Mammal (const Mammal amp; rhs);
  virtual void Speak() const 
   { 
    cout << "Mammal speak!n"; 
   }
  
  virtual Mammal* Clone() 
   { 
    return new Mammal(*this); 
   }
};
 
 Mammal::Mammal (const Mammal amp; rhs)
 {
  cout << "Mammal Copy Constructorn";
 }

 class Dog : public Mammal
{
 public:
  Dog() {}
  Dog (const Dog amp; rhs);
  void Speak()const 
   { 
    cout << "Woof!n"; 
   }
 
  virtual Mammal* Clone() 
   { 
    return new Dog(*this); 
   }
};

 Dog::Dog(const Dog amp; rhs): Mammal(rhs)
 {
  cout << "Dog copy constructor...n";
 }

 enum ANIMALS { MAMMAL, DOG};
 const int NumAnimalTypes = 2;
 int main()
{
 Mammal* theArray[NumAnimalTypes];
 Mammal* ptr;
 int choice, i;
 for ( i = 0; i<NumAnimalTypes; i  )
  {
    cout << "(1)dog (2)Mammal: ";
    cin >> choice;
  
    switch (choice)
     {
      case DOG: ptr = new Dog;
             break;
 
      default: ptr = new Mammal;
            break;
     }
    theArray[i] = ptr;
  }

 Mammal* OtherArray[NumAnimalTypes];
  for (i=0;i<NumAnimalTypes;i  )
   {
    theArray[i]->Speak();
    OtherArray[i] = theArray[i]->Clone();
   }
  for (i=0;i<NumAnimalTypes;i  )
   OtherArray[i]->Speak();
 return 0;
}

  

Вывод:

 (1)dog (2)Mammal: 1
(1)dog (2)Mammal: 2
Woof!
Mammal Copy Constructor
Dog copy constructor...
Mammal speak!
Mammal Copy Constructor
Woof!
Mammal speak!
  

Я не получил точной интуиции, лежащей в основе использования clone() метода. Это означает, что я закомментировал clone() функциональную часть в приведенном выше коде и изменил шестую последнюю строку на OtherArray[i] = theArray[i]; , и я предполагаю, что это все еще делает то, что намеревался сделать фактический код.

Мой код:

 #include <iostream>
 using namespace std;
 class Mammal
{
 public:
  Mammal() {}
  Mammal (const Mammal amp; rhs);
  virtual void Speak() const 
   { 
    cout << "Mammal speak!n"; 
   }
  
 /* virtual Mammal* Clone() 
   { 
    return new Mammal(*this); 
   } */
};
 
 Mammal::Mammal (const Mammal amp; rhs)
 {
  cout << "Mammal Copy Constructorn";
 }

 class Dog : public Mammal
{
 public:
  Dog() {}
  Dog (const Dog amp; rhs);
  void Speak()const 
   { 
    cout << "Woof!n"; 
   }
 
 /* virtual Mammal* Clone() 
   { 
    return new Dog(*this); 
   } */
};

 Dog::Dog(const Dog amp; rhs): Mammal(rhs)
 {
  cout << "Dog copy constructor...n";
 }

 enum ANIMALS { MAMMAL, DOG};
 const int NumAnimalTypes = 2;
 int main()
{
 Mammal* theArray[NumAnimalTypes];
 Mammal* ptr;
 int choice, i;
 for ( i = 0; i<NumAnimalTypes; i  )
  {
    cout << "(1)dog (2)Mammal: ";
    cin >> choice;
  
    switch (choice)
     {
      case DOG: ptr = new Dog;
             break;
 
      default: ptr = new Mammal;
            break;
     }
    theArray[i] = ptr;
  }

 Mammal* OtherArray[NumAnimalTypes];
  for (i=0;i<NumAnimalTypes;i  )
   {
    theArray[i]->Speak();
    OtherArray[i] = theArray[i];
   }
  for (i=0;i<NumAnimalTypes;i  )
 OtherArray[i]->Speak();
 return 0;
}
  

Вывод:

 (1)dog (2)Mammal: 1
(1)dog (2)Mammal: 2
Woof!
Mammal speak!
Woof!
Mammal speak!
  

Может кто-нибудь, пожалуйста, объясните мне, почему и где нам нужно использовать clone() метод и его связь с конструктором виртуальной копии. Спасибо.

Комментарии:

1. Ваша измененная версия не копирует объекты, а только указывает на них.

2. Не оставляйте виртуальный деструктор (по другим причинам). Я также отмечаю, что у ваших объектов нет данных для копирования, поэтому они не подходят для использования в случае необходимости клонирования.

3. Суть примера не в звуках животных, а в копировании, и из выходных данных ясно, что ваша версия ничего не копирует.