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

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?


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).


That's because every constructor calls by default the default base constructor:

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

will call Base().

This is defined by the standard. I for one prefer it like this rather than calling the copy constructor on the class. You can of course call it explicitly.