Making A
a virtual base class of B
and C
ensures that D
contains exactly one A
subobject[1]. For this, both B
and C
provide final overriders for foo
[2] and both are inherited by D
[2], so D
has two final overriders for foo
, making the program ill-formed[2].
When A
is not a virtual base class of B
and C
, D
will contain two distinct A
subobjects[1]. Each of these subobjects will have their own inherited final overrider for foo
[2].
[1]: N4140 §10.1 [class.mi]/4:
A base class specifier that does not contain the keyword virtual, specifies a non-virtual base class. A base class specifier that contains the keyword virtual, specifies a virtual base class. For each distinct occurrence
of a non-virtual base class in the class lattice of the most derived class, the most derived object shall contain a corresponding distinct base class subobject of that type. For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type.
[2]: §10.3 [class.virtual]/2 (emphasis mine):
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf. For convenience we say that any virtual function overrides itself. A virtual member function C::vf of a class object S is a final overrider unless the most derived class of which S is a base class subobject (if any) declares or inherits another member function that overrides vf. In a derived class, if a virtual member function of a base class subobject has more than one final overrider the program is ill-formed.