This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-12-20
[Voted into WP at October, 2009 meeting.]
Must a constructor for an abstract base class provide amem-initializer for each virtual base class from which it isdirectly or indirectly derived? Since the initialization ofvirtual base classes is performed by the most-derived class, andsince an abstract base class can never be the most-derived class,there would seem to be no reason to require constructors forabstract base classes to initialize virtual base classes.
It is not clear from the Standard whether there actually issuch a requirement or not. The relevant text is found in11.9.3 [class.base.init] paragraph 6:
All sub-objects representing virtual base classes are initialized bythe constructor of the most derived class (6.8.2 [intro.object]). If the constructor of the most derived class does notspecify amem-initializer for a virtual base classV,thenV's default constructor is called to initialize the virtualbase class subobject. IfV does not have an accessible defaultconstructor, the initialization is ill-formed. Amem-initializernaming a virtual base class shall be ignored during execution of theconstructor of any class that is not the most derived class.
This paragraph requires only that the most-derived class'sconstructor have amem-initializer for virtual base classes.Should the silence be construed as permission for constructorsof classes that are not the most-derived to omit suchmem-initializers?
Christopher Lester, on comp.std.c++, March 19, 2004:If any of you reading this posting happen to be members of the aboveworking group, I would like to encourage you to review the suggestioncontained therein, as it seems to me that the final tenor of thesubmission is both (a) correct (the silence of the standard DOESmandate the omission) and (b) describes what most users wouldintuitively expect and desire from the C++ language as well.
The suggestion is to make it clearer that constructors for abstractbase classes should not be required to provide initialisers for anyvirtual base classes they contain (as only the most-derived class hasthe job of initialising virtual base classes, and an abstract baseclass cannot possibly be a most-derived class).
For example:
struct A { A(const int i, const int j) {};};struct B1 : virtual public A { virtual void moo()=0; B1() {}; // (1) Look! not "B1() : A(5,6) {};"};struct B2 : virtual public A { virtual void cow()=0; B2() {}; // (2) Look! not "B2() : A(7,8) {};"};struct C : public B1, public B2 { C() : A(2,3) {}; void moo() {}; void cow() {};};int main() { C c; return 0;};I believe that, by not expressly forbidding it, the standard does(and should!) allow the above code. However, as the standard doesn'texpressly allow it either (have I missed something?) there appears tobe room for misunderstanding. For example, g++ version 3.2.3 (andmaybe other versions as well) rejects the above code with messageslike:
In constructor `B1::B1()':no matching function for call to `A::A()'candidates are: A::A(const A&) A::A(int, int)
Fair enough, the standard is perhaps not clear enough. But it seemsto be a shame that although this issue was first raised in 2000, weare still living with it today.
Note that we can work-around, and persuade g++ to compile the aboveby either (a) providing a default constructor A() for A, or (b)supplying default values for i and j in A(i,j), or (c) replace theconstrutors B1() and B2() with the forms shown in the two comments inthe above example.
All three of these workarounds may at times be appropriate, butequally there are other times when all of these workarounds areparticularly bad. (a) and (b) may be very bad if you are trying toenforce string contracts among objects, while (c) is just barmy (Imean why did I have to invent random numbers like 5, 6, 7 and 8 justto get the code to compile?).
So to to round up, then, my plea to the working group is:"at the very least, please make the standard clearer onthis issue, but preferrably make the decision to expressly allowcode that looks something like the above"
Proposed resolution (July, 2009):
Add the indicated text (moved from paragraph 11) to the endof 11.9.3 [class.base.init] paragraph 7:
...The initialization of each base and member constitutes afull-expression. Any expression in amem-initializer isevaluated as part of the full-expression that performs theinitialization.Amem-initializer where themem-initializer-id names a virtual base class is ignored duringexecution of a constructor of any class that is not the most derivedclass.
Change 11.9.3 [class.base.init] paragraph 8 as follows:
If a given non-static data member or base class is not named by amem-initializer-id (including the case where there is nomem-initializer-list because the constructor has noctor-initializer)and the entity is not a virtual baseclass of an abstract class (11.7.4 [class.abstract]), then
if the entity is a non-static data member that has abrace-or-equal-initializer, the entity is initialized asspecified in 9.5 [dcl.init];
otherwise, if the entity is a variant member (11.5 [class.union]), no initialization is performed;
otherwise, the entity is default-initialized (9.5 [dcl.init]).
[Note: An abstract class (11.7.4 [class.abstract]) isnever a most derived class, thus its constructors never initializevirtual base classes, therefore the correspondingmem-initializers may be omitted. —end note]After the call to a constructor for classX hascompleted...
Change 11.9.3 [class.base.init] paragraph 10 as follows:
Initialization
shall proceedproceeds in thefollowing order:
First, and only for the constructor of the most derivedclass
as described below(6.8.2 [intro.object]), virtual base classesshall beare initialized in the order they appear on a depth-firstleft-to-right traversal of the directed acyclic graph of base classes,where “left-to-right” is the order of appearance of thebase class names in the derived classbase-specifier-list.Then, direct base classes
shall beareinitialized in declaration order as they appear in thebase-specifier-list (regardless of the order of themem-initializers).Then, non-static data members
shall beare initialized in the order they were declared in theclass definition (again regardless of the order of themem-initializers).Finally, thecompound-statement of the constructor bodyis executed.
[Note: the declaration order is mandated to ensure that base andmember subobjects are destroyed in the reverse order ofinitialization. —end note]
Remove all normative text in 11.9.3 [class.base.init] paragraph11, keeping the example:
All subobjects representing virtual base classes are initializedby the constructor of the most derived class (6.8.2 [intro.object]). If the constructor of the most derived class does notspecify amem-initializer for a virtual base classV,thenV's default constructor is called to initialize thevirtual base class subobject. IfV does not have anaccessible default constructor, the initialization is ill-formed. Amem-initializer naming a virtual base class shall be ignored duringexecution of the constructor of any class that is not the most derivedclass.[Example:...