8
#include<iostream>
using namespace std;
class A
{
public:
     A(){ cout <<"1";}
     A(const A &obj){cout <<"2";}
};

class B: virtual A
{
public:
    B(){cout <<"3";}
    B(const B & obj):A(obj){cout<<"4";}
};

class C: virtual A
{
public:
   C(){cout<<"5";}
   C(const C & obj):A(obj){cout <<"6";}
};

class D:B,C
{
public:
    D(){cout<<"7";}
    D(const D & obj):C(obj),B(obj){cout <<"8";}
};

int main()
{
   D d1;
   D d(d1);
}

I am getting 13571468 as output. But I think that output should be 13572468. Why normal constructor is running instead on of copy constructor of class A?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Anurag Singh
  • 127
  • 1
  • 4

1 Answers1

12

Your code makes a copy of an instance of D, invoking its copy constructor.

Your class D's copy constructor only invokes the copy constructors of its C and B's superclasses. Because it does not invoke A's copy constructor, it gets default-constructed.

Virtually-inherited classes can be thought of as direct superclasses of the most-derived class. That's what virtual inheritance means. As such, in your instance of D, its virtually-inherited A is a direct superclass of D, and not of B or C; as such, B and C's invocations of A copy-constructor is not invoked.

When you have a virtually-inherited class, all your constructors really have two versions created "behind the scenes": one that's responsible for constructing any virtually-inherited classes, and one that's not. The one that's not does not call the virtually-inherited classes's constructors.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • 1
    Why doesn't C's copy c'tor invoke A's copy c'tor? – Amichai Aug 04 '18 at 14:52
  • 2
    Because it is not responsible for doing so. Only the most-derived class constructs all virtually-inherited superclasses. I amended my answer to explain this. If you copy-construct C, it will do it. But if you copy-construct D, it doesn't do that. D is responsible for constructing A. – Sam Varshavchik Aug 04 '18 at 14:53
  • It might be helpful to go into more detail about the fact that there are *two* copy constructors for C - and. – Martin Bonner supports Monica Aug 04 '18 at 14:56
  • If I do this D(const D & obj):C(obj),B(obj),A(obj){cout <<"8";} , then it is giving error. Can you please tell a way to call the base class i.e. A's copy contructor. – Anurag Singh Aug 04 '18 at 14:58
  • 1
    You have to explicitly declare `D` as virtually inheriting from `A`, like all other classes. Then you can invoke its copy constructor. If you don't declare it, it still virtually inherits `A`, of course. But it always uses its default constructor. – Sam Varshavchik Aug 04 '18 at 14:58
  • Thanks a lot @SamVarshavchik – Anurag Singh Aug 04 '18 at 15:12
  • @SamVarshavchik "_You have to explicitly declare D as virtually inheriting from A_" what do you mean? – curiousguy Aug 05 '18 at 14:02
  • Why, `class D:B,C,virtual A { /* with the rest being the same */` of course -- and I'm just curious what would've been more clear to you than "You have to explicitly declare D as virtually inheriting from A, like all other classes". – Sam Varshavchik Aug 06 '18 at 21:05