2

Consider the following example:

class A
{
    public:
        A()
        {
            cout<<"constructor A called: "<<this<<endl;  
        };
        
        A(A const& other) = default;
};

class B : public A
{
    public:
        B()
        {
            cout<<"constructor B called: "<<this<<endl;  
        };
        
        //This calls A's constructor
        B(B const& other)
        {
            cout<<"B copy constructor called: "<<this<<endl;    
        };

        //While this doesn't call A's constructor
        //B(B const& other) = default;
};

int main()
{
    B b;
    
    B b2(b);

    cout<<"b: "<<&b<<endl;
    cout<<"b2: "<<&b2<<endl;

    return 0;
}

Output:

constructor A called: 0x7fffc2fddda8
constructor B called: 0x7fffc2fddda8
constructor A called: 0x7fffc2fdddb0
B copy constructor called: 0x7fffc2fdddb0
b: 0x7fffc2fddda8
b2: 0x7fffc2fdddb0

Why is the constructor of A is called when copying B? Shouldn't the copy constructor of A be called instead?

However, if you change class B's copy constructor to be default, the constructor of A is not called when copying which makes sense.

It will be nice if someone can give a reasonable explanation as to why.

Christian
  • 4,902
  • 4
  • 24
  • 42
Eds
  • 380
  • 1
  • 13
  • 3
    Appropriate base class constructors always are called prior to the derived classes ones. I don't fully understand your concerns? – πάντα ῥεῖ Mar 22 '22 at 21:55
  • @πάνταῥεῖ I have edited my question, I hope it makes more sense now – Eds Mar 22 '22 at 22:16
  • 1
    `B(B const& other) { ... }` doesn't ask for the copy constructor. That would be `B(B const& other): A(other) { ... }` – user4581301 Mar 22 '22 at 22:29
  • @user4581301 Sure that will call A's copy constructor and won't call A's constructor right? – Eds Mar 22 '22 at 22:43
  • 1
    Does this answer your question? [Why does the implicit copy constructor calls the base class copy constructor and the defined copy constructor doesn't?](https://stackoverflow.com/questions/9178204/why-does-the-implicit-copy-constructor-calls-the-base-class-copy-constructor-and) or perhaps [How to declare copy constructor in derived class, without default construcor in base?](https://stackoverflow.com/questions/9309577/how-to-declare-copy-constructor-in-derived-class-without-default-construcor-in) – JaMiT Mar 22 '22 at 23:05

1 Answers1

3

Why is the constructor of A is called when copying B? Shouldn't the copy constructor of A be called instead?

No, it shouldn't.

A derived class must always initialize a base class. If the derived class has a constructor that is implemented explicitly by the user, but it does not explicitly call a base class constructor in its member initialization list, the compiler will make an implicit call to the base class's default constructor, regardless of the type of the derived constructor. The compiler does not make any assumption about the user's intent in implementing the derived constructor. If the user wants a specific base class constructor to be called, they need to make that call themselves.

Since B has an explicitly implemented copy constructor that lacks a member initialization list, the compiler initializes A by calling its default constructor, not its copy constructor.

IOW, this:

B(B const& other)
{
    ...
}

Is equivalent to this:

B(B const& other) : A()
{
    ...
}

NOT to this, as you are thinking:

B(B const& other) : A(other)
{
    ...
}

However, if you change class B's copy constructor to be default, the constructor of A is not called when copying which makes sense.

Correct, a default'ed copy constructor will call the base class's copy constructor, not its default constructor. The compiler is implicitly implementing the entire derived constructor, and so it will choose the appropriate base class constructor to call.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770