3

使用虚拟复制构造函数,类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());

有什么缺点(除了它仅适用于“就地”创建)?现在没有人必须实现克隆,一切似乎都容易多了。

4

4 回答 4

4

它们的重点是当您拥有指向基类的现有指针并想要“无论它是什么”的副本时。

考虑:

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?
};

在这里和这里查看我的答案

于 2013-05-01T13:06:53.550 回答
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 的生命周期。

编辑:它必须是一个虚函数,这样Carand MotorBikeandTruck可以根据它实际是什么对象来做不同的事情。

于 2013-05-01T13:04:43.077 回答
1

因为您的第二个示例不遵循三规则,因此如果 Foo 被复制(例如,如果您曾经在 std::vector 中使用过 Foo )将会崩溃。

大多数情况下,在 C++ 中,您需要有效的复制构造函数,而 clone 是一个很好的方法。

于 2013-05-01T13:02:49.097 回答
1

想象一下:

Car *c = new Car();
Foo f1(c);
Foo f2(c);

...然后在调用 Foo 析构函数时观看烟花。

于 2013-05-01T13:02:50.333 回答