39

Consider a class hierarchy where A is the base class and B derives from A.

If the copy constructor is not defined in B, the compiler will synthesize one. When invoked, this copy constructor will call the base class copy constructor (even the synthesized one, if none has been provided by the user).

#include <iostream>

class A {
    int a;
public:
    A() {
        std::cout << "A::Default constructor" << std::endl;
    }

    A(const A& rhs) {
        std::cout << "A::Copy constructor" << std::endl;
    }
};

class B : public A {
    int b;
public:
    B() {
        std::cout << "B::Default constructor" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    std::cout << "Creating B" << std::endl;
    B b1;
    std::cout << "Creating B by copy" << std::endl;
    B b2(b1);
    return 0;
}

Output:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor

If the user defines its own copy constructor in B, when invoked, this copy constructor will call the base class default constructor, unless a call to the base class copy constructor is explicitly present (e.g. in the initialization list).

#include <iostream>

class A {
    int a;
public:
    A() {
        std::cout << "A::Default constructor" << std::endl;
    }

    A(const A& rhs) {
        std::cout << "A::Copy constructor" << std::endl;
    }
};

class B : public A {
    int b;
public:
    B() {
        std::cout << "B::Default constructor" << std::endl;
    }
    B(const B& rhs) {
        std::cout << "B::Copy constructor" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    std::cout << "Creating B" << std::endl;
    B b1;
    std::cout << "Creating B by copy" << std::endl;
    B b2(b1);
    return 0;
}

Output:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Default constructor
B::Copy constructor

My question is, why doesn't the user defined copy constructor call the base class copy constructor as a default behavior?

John_West
  • 2,239
  • 4
  • 24
  • 44
Vincenzo Pii
  • 18,961
  • 8
  • 39
  • 49
  • 2
    If it was that way per default, how would you specify the case where you wouldn't want that to happen? – PlasmaHH Feb 07 '12 at 14:48
  • @PlasmaHH `ParentClass()` in the initializer list. That would still be pretty inconsistent and confusing I believe. – Mark B Feb 07 '12 at 14:50
  • @MarkB: Indeed, I was hoping he comes to the same conclusion when thinking about it... – PlasmaHH Feb 07 '12 at 14:52
  • @PlasmaHH Exactly my first question as well. – Matt Phillips Feb 07 '12 at 14:57
  • 2
    Because the standards committee had a choice and made the most logical choice in my opinion (If you don't specify how to call the base class constructor then you must mean the default one (the one with no parameters) as you have specified no parameters). – Martin York Feb 07 '12 at 15:09
  • 2
    also note the same logic applies to all members as well as the base classes. – Mooing Duck Feb 07 '12 at 15:42
  • I appreciate all of the answers and comments, thanks for your inputs. The fact seems to be that, per default, it is consistent to always call the default constructor, unless a different one is explicitly requested. That sounds perfect and clean to me and I'm also happy (as a developer) that the implicit copy constructor calls the base class copy constructor. But if the "call the default constructor in any constructor, as a default" principle exists, then the implicit copy constructor constitutes an (appreciated) exception to the rule! – Vincenzo Pii Feb 07 '12 at 17:10
  • Your question is the clearest answer to my question I've found ... Jeopardy style. – davidhigh May 06 '15 at 16:53

3 Answers3

9

That's just the way the implicit copy constructor is defined (it wouldn't make sense calling the default). As soon as you define any constructor (copy or otherwise) its normal automatic behavior is to call the default parent constructor, so it would be inconsistent to change that for one specific user-defined constructor.

Mark B
  • 95,107
  • 10
  • 109
  • 188
9

All base child constructors call the parent default constructor. This is how the standard is defined. As you pointed out if you wanted the derive class B to call A's copy constructor you have to explicitly ask for it

#include <iostream>

class A {
int a;
public:
A() {
    std::cout << "A::Default constructor" << std::endl;
}

A(const A& rhs) {
    std::cout << "A::Copy constructor" << std::endl;
}
};

class B : public A {
int b;
public:
B() {
    std::cout << "B::Default constructor" << std::endl;
}
B(const B& rhs):A(rhs) {
    std::cout << "B::Copy constructor" << std::endl;
}
};

int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating B by copy" << std::endl;
B b2(b1);
return 0;
}

This is so because the compiler can't know for each different constructor which constuctor of the parent should be called and hence we have the default constructors For all others you have to explicitly state them.

Output:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor
B::Copy constructor
Swapnil
  • 389
  • 5
  • 22
Lefteris
  • 3,196
  • 5
  • 31
  • 52
  • 9
    `All base child constructors call the parent default constructor.`... except for the implicit copy constructor :)! – Vincenzo Pii Feb 07 '12 at 17:14
  • Implicit copy constructor is an explicit name for a most primitive operation provided by the compiler, bitwise copy of source to destination. IMO its just a fancy name. – shakthi May 19 '17 at 19:33
3

The simple (possibly trite) answer is because you didn't tell it to. Since you are writing the derived copy constructor, you completely control how it behaves. Failure to specify a call to the base and the compiler generates code to initialize the base class by calling the base classes default constructor.

Lou
  • 1,955
  • 14
  • 16