使用虚拟副本构造函数,类Vehicle
具有copy()
虚拟成员函数,所有继承的类都将实现Car
。
稍后其他一些类可以将任何类型的车辆作为成员变量:
struct Foo {
Vehicle *v;
Foo(const Vehicle &veh) {
v = veh.clone();
}
};
我没有看到这一点。为什么不像这样摆脱clone()
和new
“”
struct Foo {
Vehicle *v;
Foo(Vehicle *veh) {
v = veh; //veh has no clone()
}
~Foo() {
delete v;
}
};
//elsewhere
Foo f(new Car());
有什么缺点(除了它只适用于“就地”创作)?现在没有人必须实现克隆,一切似乎都更容易。
答案 0 :(得分:2)
嗯,在你的例子中,它工作正常。但是如果:
Foo* MakeCar()
{
Car c;
Foo *f = new Foo(&c);
}
或:
Car *c = new Car;
Foo f(c);
delete c;
... use f in a way that needs c here.
通过克隆对象,您不会遇到我刚才创建的问题。 Foo对象完全控制Car的寿命。
编辑:它必须是虚拟函数,因此Car
和MotorBike
以及Truck
可以根据实际的对象执行不同的操作。
答案 1 :(得分:2)
他们的观点是当你有一个现有的指向基类的指针并想要一个“它是什么”的副本。
考虑:
class Base;
class Derived1 : public Base;
class Derived2 : public Base;
Derived1* d1 = new Derived1();
Derived2* d2 = new Derived2();
makeACopy(d1);
makeACopy(d2);
void makeACopy(Base* base) {
// ??? What is it?
};
请参阅my answer here以及here。
答案 2 :(得分:1)
因为你的第二个例子不遵循三个规则,因此如果复制了Foo会因此崩溃(例如,如果你曾经在std :: vector中使用过Foo)。
大多数情况下,在C ++中,您需要使用工作副本构造函数,克隆是一种很好的方法。
答案 3 :(得分:1)
想象一下:
Car *c = new Car();
Foo f1(c);
Foo f2(c);
...然后在调用Foo析构函数时观看烟火。