Code Sample:
Consider the following diamond hierarchy:
struct A
{
virtual void f(){}
void g(){}
};
struct B : virtual A
{
virtual void f() override{}
void g(){}
};
struct C : virtual A
{
};
struct D: B, C
{
};
int main()
{
D d;
d.f(); //B::f is called
d.g(); //B::g is called
}
What I Do Understand:
As far as the non-virtual function g
is concerned, everything is clear: the name B::g
hides A::g
, even though the name A::g
could be reached without being hidden through C
. There is no ambiguity. B::g
is called. The standard explicitly confirms this in 10.2 p.10:
[ Note: When virtual base classes are used, a hidden declaration can be reached along a path through the subobject lattice that does not pass through the hiding declaration. This is not an ambiguity. The identical use with non-virtual base classes is an ambiguity; in that case there is no unique instance of the name that hides all the others. — end note ] [Example:
Additionally, this answer to a related question provided an exhaustive explanation of the issue.
The Problem:
What I don't understand is how the quote mentioned above pertains to the virtual function f
. There is no name hiding involved with f
, is there? Only overriding is involved, and 10.3 p.2 reads:
A virtual member function C::vf of a class object S is a final overrider unless the most derived class (1.8) 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.
Now, it seems to me, that the virtual function f
exactly fits the definition of not having a final overrider and the program should be ill-formed. But it's not. Or is it? MSVC compiles it just fine, with the following warning:
warning C4250: 'D' : inherits 'B::B::f' via dominance
To be honest, I had never come across the term "dominance" before. When I search it in the standard, it has a single occurrence, in the index, and refers me to the chapter where my first quote comes from. And, as I already mentioned, the quote seems to pertain only to name hiding rather than virtual function overriding.
Questions:
- Does
f
have more than one final overrider in D? - Does the rule of dominance apply in this case? How does it follow from the standard?
C::f()
called? - it doesn't count as a virtual member function? (being inherited from A) – Mopey