虚拟拷贝构造函数(克隆函数)有什么意义?

时间:2013-05-01 13:00:24

标签: c++

使用虚拟副本构造函数,类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 个答案:

答案 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的寿命。

编辑:它必须是虚拟函数,因此CarMotorBike以及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析构函数时观看烟火。