Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't copy constructors "chained" like default constructors and destructors?

Tags:

Why aren't copy constructors chained (like default ctors or dtors) so that before the derived class's copy constructor is called, the base class's copy constructor is called? With default constructors and destructors, they are called in a chain from base-to-derived and derived-to-base, respectively. Why isn't this the case for copy constructors? For example, this code:

class Base { public:     Base() : basedata(rand()) { }      Base(const Base& src) : basedata(src.basedata) {         cout << "Base::Base(const Base&)" << endl;     }      void printdata() {         cout << basedata << endl;     }  private:     int basedata; };  class Derived : public Base { public:     Derived() { }      Derived(const Derived& d) {         cout << "Derived::Derived(const Derived&)" << endl;     } };   srand(time(0));   Derived d1;      // basedata is initialised to rand() thanks to Base::Base()  d1.printdata();  // prints the random number  Derived d2 = d1; // basedata is initialised to rand() again from Base::Base()                  // Derived::Derived(const Derived&) is called but not                  // Base::Base(const Base&)  d2.printdata();  // prints a different random number 

The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access basedata to change it.

Is there something fundamental I'm missing about copy constructors so that my mental model is incorrect, or is there some arcane (or not arcane) reason for this design?

like image 643
Seth Carnegie Avatar asked Jan 07 '12 20:01

Seth Carnegie


People also ask

Is copy constructor and default constructor?

The default constructor does only shallow copy. Deep copy is possible only with a user-defined copy constructor. In a user-defined copy constructor, we make sure that pointers (or references) of copied objects point to new memory locations.

Are copy constructors default?

@DavidHammen A "default copy constructor" is a default constructor (can be called with no arguments) and a copy constructor (can be called with one argument of the same type). You can throw in as many additional parameters as you want, as long as all of them have default arguments.

Why copy constructor is not used in Java?

In C++ that statement makes a copy of the object's state. In Java it simply copies the reference. The object's state is not copied so implicitly calling the copy constructor makes no sense. And that's all there is to it really.

Why copy constructor Cannot use pointer?

Passing by references ensures an actual object is passed to the copy constructor, whilst a pointer can have NULL value, and make the constructor fail.


2 Answers

The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access pdata to change it.

Sure it can:

Derived(const Derived& d)     : Base(d) {     cout << "Derived::Derived(const B&)" << endl; } 

If you don't specify a base class constructor in the initializer list, its default constructor is called. If you want a constructor other than the default constructor to be called, you must specify which constructor (and with which arguments) you want to call.

As for why this is the case: why should a copy constructor be any different from any other constructor? As an example of a practical problem:

struct Base {     Base() { }     Base(Base volatile&) { } // (1)     Base(Base const&)    { } // (2) };  struct Derived : Base {     Derived(Derived&) { } }; 

Which of the Base copy constructors would you expect the Derived copy constructor to call?

like image 186
James McNellis Avatar answered Sep 19 '22 18:09

James McNellis


You can:

Derived(const Derived& d) : Base(d) {     cout << "Derived::Derived(const B&)" << endl; } 

This calls the Base copy constructor on the Base sub-object of d.

The answer for 'why' I don't know. But usually there's no answer. The committee just had to choose one option or the other. This seems more consistent with the rest of the language, where e.g. Derived(int x) won't automatically call Base(x).

like image 37
Yakov Galka Avatar answered Sep 21 '22 18:09

Yakov Galka