Copy Constructor not Called in Virtual Inheritance

Apr 10, 2013 at 3:53pm
I have the following classes and 'dreaded diamond':


   A
  / \
 /   \
B     C
 \   /
  \ /
   D
   |
   |
   E


Classes B & C both inherit from A using public virtual A.
E is the only concrete class. None of the classes are totally abstract.
Every class has a copy constructor.
All of the copy constructors are chained together through the initialization lists.
E correctly calls D's copy constructor.
D correctly calls B and C's copy constructors.
But neither B nor C call A's copy constructor, although A's default constructor is called. To reiterate B and C have a call to A's copy constructor in their initialization lists.

I guess A's default constructor is being called is because of virtual inheritence, but why isn't its copy constructor called (too)?
A's copy constructor includes some very important code and I could do with calling it. Should I call it from the concrete class' initialization list or is that considered bad form?
Last edited on Apr 10, 2013 at 3:58pm
Apr 10, 2013 at 4:04pm
With virtual inheritance it is the responsibility of a class to call the correct constructor of all virtually inherited base classes from its own constructors. This has to happen to resolve the conflict of the possibility of B and C having different ctor calls to A.
Last edited on Apr 10, 2013 at 4:06pm
Apr 10, 2013 at 4:11pm
Thanks for the explanation, but I'm a little confused by your solution.

Which class has the responsibility of calling the base class from its own constructors? B and C are currently fullfilling that responsibility, but I guess that is ambiguous and is why it doesn't work? So should class D (the class at the diamond point) or E (the last concrete class) have that responsibility? Or is the choice up to me?

Reg.
Apr 10, 2013 at 4:19pm
In your case, D virtually inherits A, so it is D's responsibility.

Just remember this: If class X inherits from class Y, and class Y inherits from class Z with the virtual keyword, then X must call Z's constructors.

For you, E just inherits D and since D doesn't extend any classes with the virtual keyword, E has no responsibilities.

Basically, you handle classes two levels up if those classes were inherited with the virtual keyword one level up. "virtual" inheritance means "let the next class to extend me handle it if I'm not the concrete one."


I was wrong, see: http://www.cplusplus.com/forum/general/98582/#msg529927
Last edited on Apr 10, 2013 at 6:11pm
Apr 10, 2013 at 4:24pm
Thanks for your help. Nice and clear.
Apr 10, 2013 at 4:35pm
Sorry, spoke too soon...

Calling class A's copy constructor from class D's copy constructor's initialization list doesn't work. Class A's copy constructor is left uncalled.

Is the initialization list the correct place to call it from?
Calling it from the body doesn't work because A is abstract.
Apr 10, 2013 at 4:41pm
I've moved it to class E and that has worked.
I seem to remember once reading something about 'the most derived class' and virtual inheritance. Could that be it?
Apr 10, 2013 at 4:47pm
I was wrong, apparently all further classes in the chain are responsible for A.

http://ideone.com/pDVKKd

The most derived handles it, but all have to be responsible in case they are the ones instantiated.
Last edited on Apr 10, 2013 at 4:47pm
Apr 10, 2013 at 4:49pm
Wow, talk about going the extra mile.
Most derived class it is.

Thanks.
Topic archived. No new replies allowed.