copy constructor

Pages: 12
I think you are mixing up copy ctors with the clone function.

The clone function does not actually copy anything. It just invokes the desired copy ctor. In order to actually copy an object, you need a functioning copy ctor.

In my understanding, the clone() method creates a new object of the type passed in.


This is correct.

But when one says you are doing a deep copy it means that you have allocated new memory on the heap and have copied each and every element of the object being copied from.


Whether or not this is true depends on how the copy constructor is formed. A proper copy ctor will copy all of it's members appropriately.

All clone does is make it so you don't need to know what kind of vehicle you're copying. if 'a' is a Car, then 'a->clone();' makes an identical Car. if 'a' is a Truck, then 'a->clone()' makes an identical Truck.

How it makes an identical Truck/Car depends on Truck's/Car's copy constructor. If they don't properly copy themselves then of course it won't work. Cloning depends on the copy ctor.

in the copy ctor of the Person how does that resort to deep copy when say vehicle a has done some car modification() and you need that to be reflected in vehicle b.


If Car's copy ctor properly copies itself, all modifications should be reflected in the copy.

In the arr class, i did a clone() that would have created a new object just like it would have created a new object for the abstract method()...so why the difference?


Your arr class did not properly copy itself. It failed to do a deep copy of its 'p' member.
I understand, so all clone() does is to give you the type object at runtime, but it is the job of the copy ctor to define how the copy will go. Hence lets say we do this in the Person copy constructor,
Firstly how would you then define what to copy if you do not know what is the object.

lets say :
c
1
2
3
4
5
6
7
8
9
10
11
12
lass car:vehicle
{
modifies exhaust();
}
class bike:vehicle
{
modified breaks();
}
class truck:vehicle
{
modified suspension();
}


now yes by doing vehicle *b = a->clone();

b will be of the class type in a. But now you wouldnt know that in your copy constructor of Person so how you know that you will have to modify the breaks or the exhaust.
1
2
3
4
5
6
7
8
9
10
11
class Person
{
public:  
vehicle *v;
Person(const Person &p)
{
   this->v = p.v->clone();//fine now we get a new object type
  //now how would you copy the modfied values into this since it could be 
  (this->v)->modified_breaks = (p->v)->modified_?;//since we have no idea what to copy over
}
};


however this approach seems like better since you could add,

1
2
3
4
5
6
7
8
9
if( a_is_a_Car )
  b = new Car( *static_cast<Car*>(a) );
b->modified_exhaust = p->modified_exhaust;
if( a_is_a_Bike )
  b = new Bike( *static_cast<Bike*>(a) );
b->modified_breaks = p->modified_breaks;
if( a_is_a_Truck )
  b = new Truck( *static_cast<Truck*>(a) );
b->modified_suspension = p->modified_suspension;
Last edited on
I understand, so all clone() does is to give you the type object at runtime, but it is the job of the copy ctor to define how the copy will go.


Correct!

But now you wouldnt know that in your copy constructor of Person so how you know that you will have to modify the breaks or the exhaust.

...

(this->v)->modified_breaks = (p->v)->modified_?;//since we have no idea what to copy over


You don't do this. Car/Truck/Bike's copy ctor will have already copied that information. Person doesn't have to worry or care about it.
Car/Truck/Bike's copy ctor will have already copied that information. Person doesn't have to worry or care about it. 


how would that be when its the person class that needs a copy.

1
2
3
4
Person obj1;
obj1.v = new car;
(obj1.v)->modified_exhaust();//it could do whatever
Person obj2 = obj1;//now obj2.v will have a new car but what abt that modification 


Could you explain how at such a copy ctor at class car for example could help?
Okay...

modified_exhaust is a member of Car, right?

So it works like this:

Person copy ctor calls vehicle->clone()
vehicle->clone() calls Car's copy ctor
Car's copy ctor copies modified_exhaust to the new Car
Therefore the new Person has a complete copy of the car, including all modifications done to it.


Person only worries about copying Person members. If it's a member of Car/Vehicle/Whatever, then let Car/Vehicle/Whatever's copy ctor handle it. Here, modified_exhaust is not a member of Person, so Person doesn't care about it.


Could you explain how at such a copy ctor at class car for example could help?


sure:

1
2
3
4
5
6
7
8
9
10
11
12
class Car : public Vehicle
{
  int modified_exhaust;

public:
  virtual Car* clone() { return new Car(*this); } // implement the clone

  Car(const Car& v)
  {
    modified_exhaust = v.modified_exhaust;  // copy the exhaust information
  }
};


Of course since this copy is so trivial (nothing needs to be deep copied), you don't even need to write this copy ctor. You can just use the compiler provided copy ctor:

1
2
3
4
5
6
7
8
9
10
11
class Car : public Vehicle
{
  int modified_exhaust;

public:
  virtual Car* clone() { return new Car(*this); } // implement the clone

  // don't write any copy ctor
  //   the compiler will provide a "default" copy ctor that shallow copies all members for you
  //   the default copy ctor will work fine for this class because nothing needs a deep copy
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person{
 55 public:
 56         vehicle *v;
 57         Person(){}
 58         Person(const Person& p){this->v = (p.v)->clone();}
 59 };
 

60 int main()
 61 {
 62   Person Obj1;
 63   Obj1.v = new Car;
 64   (Obj1.v)->set(123);//this does the modification, allocates memroy on heap and sets that value to  123
 65   (Obj1.v)->display();
 66 
 67 Person Obj2 = Obj1;
 68 delete (Obj1.v);//purposely did this to check if I have separate memory for  Obj2
 69 (Obj2.v)->display();
}



is this how it would look like together with the method in the class car as you have defined. How would clone() invoke the car copy constructor when its just construtors getting involved here?(only person cpy ctor is called)

car constructor
car: 123
car destructor
car: 123

Last edited on
(Obj1.v)->set(123);//this does the modification, allocates memroy on heap and sets that value to 123


Well now if you're allocating memory on the heap, you'd need to do a deep copy, so the compiler supplied copy ctor won't work anymore.

But basically yes that is the right idea. As long as Car's copy ctor properly copies itself.

How would clone() invoke the car copy constructor when its just construtors getting involved here?(only person cpy ctor is called)


clone invokes the car copy ctor here:

1
2
3
4
5
6
7
8
class Car
{
public:
  virtual Car* clone()
  {
    return new Car(*this);  // <- new Car(..) calls the copy ctor
  }
};


In your above example... Car has 2 ctors running. The default ctor (when Obj1 is created), and the copy ctor (when it is copied). However you only seem to be logging the default ctor and are not logging the copy ctor.
I think im getting it now..thanks Disch....

clone invokes the car copy ctor here:
1
2
3
4
5
6
7
8
9
10
11
12
class Car : public Vehicle
{
  int modified_exhaust;

public:
  virtual Car* clone() { return new Car(*this); } // copy ctor is called

  Car(const Car& v)
  {
    this->modified_exhaust = v.modified_exhaust;  // what is the this pointer here. v is the obj1 this pointer
  }
};

Since the this pointer refers to obj1 then what is the this pointer in the copy constructor
in the contructor... 'this' is the object being constructed.

so if you are copying obj1 to obj2, then:
v = obj1 (the source object being copied)
this = obj2 (the copy)
Topic archived. No new replies allowed.
Pages: 12