存储可变数量的派生class的可变数量的对象并对其进行深度复制

Store a variable number of objects of a variable number of derived class and deep copy them

我对如何在 C++ 中实现类似的东西感到有点困惑。我觉得这可能与我的架构有关。
假设我在蒙特利尔有一个车库,在这个车库里,有不同的 cars.I 通常会带有指向基 class Car 的指针向量。但问题是,我想深入复制车库并在迈阿密开设一个。此外,Saab 汽车需要具有不同的复制构造函数,但具有相同的签名。 以后还会有其他类似的例外情况。我事先不知道车库里有什么。这是我目前的代码。

        //base class
        class Car
        {
            public:

                Car(int speed);

            private:
                int speed;

        }
        class Garage
        {
               public:
                      Garage(){};
                      //copy constructor of the garage
                      Garage(const Garage &toCopy)
                      {
                         for(int i=0;i<toCopy.cars.size();i++)
                         {
                         ReceiveCar(*cars[i]);
                         }
                      }
                      vector<std::shared<Car>> cars;
                      template <typename T>
                      T* ReceiveCar()
                      {
                         std::shared_ptr<T> ptr = std::make_shared<T>();
                         cars.push_back(ptr);
                         return ptr.get();
                      }
                      T* ReceiveCar(Car &toCopy)
                      {
                         std::shared_ptr<T> ptr = std::make_shared<T>(toCopy)                     cars.push_back(ptr);
                         return ptr.get();
                       }

            }
      class Saab : public Car
    {
        public:
              Saab(int speed)
                :Car(speed)
              {
                 DoWork();
              };
    }
    class AstonMartin: public Car
    {
        public:
              AstonMartin(int speed)
                  :Car(speed)
              {
                 DoImportantStuff();
              };
              AstonMartin(const AstonMartin& toCopy)
                  :Car(toCopy.speed)
              {
                 DoImportantStuff();
              };
    }  

当然,使用的拷贝构造函数是来自Car的隐式拷贝构造函数。是否可以调用派生的 class' 而不是在 ifs/elses 之间为规则的每个例外进行动态转换。也许以某种方式用指针存储每个派生的 classes?
PS:我知道我不应该返回原始指针,但是汽车的析构函数在我的代码中是私有的,所以 shared_pointers 仍然是安全的。

通常的解决方案是使用虚拟 clone() 方法来创建对象的副本,而不是使用复制构造函数。

在继承的上下文中,复制构造函数应该设计为所谓的“虚拟复制构造函数”。这些函数通常称为 copySelf、cloneSelf 或简称为 clone。

这是您使用复制构造函数和虚拟复制构造函数的详细示例:

#include <memory>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;

//base class
class Car
{ public:
    Car(int speed): speed(speed) {};
    Car(const Car& c): speed(c.speed)
    { cout <<"Copy Constructor Car" <<endl;
    }
    virtual void display()
    { cout <<" speed: " <<speed <<endl;
    }
    virtual Car* clone()const =0;  // virtual copy constructor
  private:
    int speed;
};
typedef std::shared_ptr<Car> CarP;
class Garage
{ private:
    vector<CarP> cars;
  public:
    Garage() {}
    //copy constructor of the garage
    Garage(const Garage &toCopy)
    { cout <<"Copy Constructor Garage" <<endl;
      for (CarP c : toCopy.cars)
      { CarP cp(c->clone());
        ReceiveCar(cp);
      }
    }
    void ReceiveCar(CarP toCopy)
    { cars.push_back(toCopy);
    }
    void display()
    { for (CarP c : cars)  c->display();
    }
};
class Saab: public Car
{ public:
    Saab(int speed): Car(speed)
    { cout <<"Constructor Saab" <<endl;
    }
    void display()
    { cout <<"Car: Saab";  Car::display();
    }
    Saab* clone()const
    { return new Saab(*this);
    }
};
class AstonMartin: public Car
{ public:
    AstonMartin(int speed): Car(speed)
    { cout <<"Constructor AstonMartin" <<endl;
    }
    AstonMartin(const AstonMartin& toCopy): Car(toCopy)
    { cout <<"Copy Constructor AstonMartin" <<endl;
    }
    void display()
    { cout <<"Car: AstonMartin";  Car::display();
    }
    AstonMartin* clone()const
    { return new AstonMartin(*this);
    }
};
int main()
{
  CarP saab  =std::make_shared <Saab>(100);
  CarP aston =std::make_shared <AstonMartin>(200);
  Garage montreal;
  montreal.ReceiveCar(saab);
  montreal.ReceiveCar(aston);
  montreal.display();
  Garage miami(montreal);  // your decision to offer the user a copy constructor:
  miami.display();
}

产生的输出:

Constructor Saab
Constructor AstonMartin
Car: Saab speed: 100
Car: AstonMartin speed: 200
Copy Constructor Garage
Copy Constructor Car
Copy Constructor Car
Copy Constructor AstonMartin
Car: Saab speed: 100
Car: AstonMartin speed: 200