存储可变数量的派生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
我对如何在 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