The C++11 standard says in 12.6.2/10:
In a non-delegating constructor, initialization proceeds in the
following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order
they appear on a depth-first left-to-right traversal of the directed
acyclic graph of base classes, where “left-to-right” is the order of
appearance of the base classes in the derived class
base-specifier-list.
— [direct base classes etc. ...]
This says it, basically -- the most derived class is responsible for initialization in whatever way it defines it (in the OP: it doesn't, which leads to default initialization). The subsequent example in the standard features a similar scenario as in the OP here, just with an int argument to the ctor; only the default ctor of the virtual base is called, because no explicit "mem-initializer" for the virtual base is provided in the most derived class.
Of interest, although nor directly applying here, is also 12.6.2/7:
A mem-initializer [the A()
in a possible B(): A() {}
. -pas] where the mem-initializer-id denotes a virtual base
class is ignored during execution of a constructor of any class that
is not the most derived class.
(I find that pretty tough. The language basically says "I don't care what you coded, I'm gonna ignore it." There are not so many places where it can do that, violating as-if.) That constructor of a not-most-derived-class would be B()
. The sentence does not directly apply here because there is no explicit constructor in B
, so there is no mem-initializer either. But although I could not find wording for that in the standard one must assume (and it is consistent) that the same rule applies for the generated copy constructor.
For completeness, Stroustrup says in "The C++ Programming Language" (4.ed, 21.2.5.1) about a most derived class D with a virtual base V down the road somewhere:
The fact that V wasn't explicitly mentioned as a base of D is irrelevant. Knowledge of a virtual base and the obligation to initialize it "bubbles up" to the most derived class. A virtual base is always considered a direct base of its most derived class.
That is exactly what Sam Varshavchik said in an earlier post.
Stroustrup then goes on to discuss that deriving a class DD from D makes it necessary to move V's intialization to DD, which "can be a nuisance. That ought to encourage us not to overuse virtual base classes."
I find it fairly obscure and dangerous that a base class stays uninitialized (well, more precisely: default-initialized) unless the most-derived class explicitly does something.
The author of the most-derived class must dive deep into
an inheritance hierarchy s/he may have no interest in or documentation about and cannot rely on e.g. the library s/he uses to do the right thing (the library can't).
I'm also not sure I agree with the rationale given in other posts ("which of the various intermediate classes should perform the initialization?"). The standard has a clear notion of the initialization order ("depth-first left-to-right traversal"). Couldn't it mandate that the first class encountered which virtually inherits from a base performs the initialization?
The interesting fact that the default copy ctor does initialize the virtual base is prescribed in 12.8/15:
Each base or non-static data member is copied/moved in the manner
appropriate to its type:
[...]
— otherwise, the base or member is
direct-initialized with the corresponding base or member of x.
Virtual
base class subobjects shall be initialized only once by the
implicitly-defined copy/move constructor (see 12.6.2).
In any event, because C
is the most derived class it is C
's (and not B
's) responsibility to copy-construct the virtual base A
.
A
is constructed when a C is copied which doesn't seem right to me (it should be copy-constructed, calling the default copy ctor, afaics, as happens when a B is copied).