3

With virtual copy constructors, a class Vehicle has a copy() virtual member function that all inherited classes like Car will implement.

Later some other class can have any type of vehicle as a member variable:

struct Foo {
  Vehicle *v;
  Foo(const Vehicle &veh) {
    v = veh.clone();
  }
};

I don't see the point. Why not get rid of clone() and do new "in place" like this

struct Foo {
  Vehicle *v;
  Foo(Vehicle *veh) {
    v = veh; //veh has no clone()
  }
  ~Foo() {
    delete v;
  }
};

//elsewhere
Foo f(new Car());

What are the drawbacks (other than it only working for "in place" creation)? Now nobody has to implement clone and everything seems much easier.

7cows
  • 4,974
  • 6
  • 25
  • 30

4 Answers4

4

The point of them is when you have an existing pointer to a base class and want a copy of "whatever it is".

Consider:

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

See my answer here and also here.

Community
  • 1
  • 1
Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • I don't get this. What's makeACopy doing? – 7cows May 01 '13 at 13:26
  • @7Cows, it was supposed to be illustrative ;) Check out the other answers. Cloning is used when we have a pointer to the base-class and want a copy of the concrete class *whatever it may be*. – Moo-Juice May 01 '13 at 13:47
2

Well, in your example, it works fine. But what if:

 Foo* MakeCar()
 {
    Car c;
    Foo *f = new Foo(&c); 
 }

or:

 Car *c = new Car;
 Foo f(c);
 delete c;
 ... use f in a way that needs c here. 

By cloning the object, you don't have the problems that I've just created above. The Foo object is fully in control of the lifetime of the Car.

Edit: and it has to be a virtual function, so that Car and MotorBike and Truck can do different things depending on what object it actually is.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Can the clone function be avoided if we know that: A) The objects are "immutable", i.e. cannot be changed by anyone after they are created. B) We use smart pointers (shared_ptr) to the objects? Is that a good idea? – 7cows May 01 '13 at 15:14
  • 1
    Immutability won't help in either of the cases I showed above. I think a smart pointer can't point at a local object, and it tracks the lifetime of the object, so that will probably work. As far as I'm aware, smart pointers are always a good idea. – Mats Petersson May 01 '13 at 16:38
1

Because your second example doesn't follow the rule of three, and will therefore crash if Foo is ever copied (for instance if you ever used Foo in a std::vector).

Most of the time in C++ you need working copy constructors, and clone is a good way to have that.

john
  • 7,897
  • 29
  • 27
1

Imagine this:

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

...then watch the fireworks when the Foo destructors are called.

sje397
  • 41,293
  • 8
  • 87
  • 103