What is dominance in the context of virtual functions?

Code example:

Consider the following hierarchy of diamonds:

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; df(); //B::f is called dg(); //B::g is called } 

What I understand:

As for the non-virtual function g , everything is clear: the name B::g hides A::g , even if the name A::g can be reached without hiding through C There is no ambiguity. B::g . The standard clearly confirms this in 10.2 s .10:

[Note. When virtual base classes are used, a hidden declaration can be reached along the way through a subobjective lattice that does not pass through the hidden declaration. This is not an ambiguity. Identical use with non-virtual base classes is ambiguous; in this case there is no unique instance of the name that hides everyone else. - end note] [Example:

In addition, this answer to the relevant question provided a comprehensive explanation of the problem.

Problem:

I do not understand how the quote above refers to the virtual function f . There is no name associated with f , is there? Only overriding is enabled, and 10.3 s .2 reads:

A valid member function of C :: vf of an object of class S is the final overrider if only the most derived class (1.8) from which S is the base subobject of the class (if any) declares or inherits another member function that overrides vf. In a derived class, if a virtual member function of a subobject of the base class has more than one final redefinition of the program is poorly formed.

Now it seems to me that the virtual function f exactly matches the definition of not having a final assignment, and the program should be poorly formed. But this is not so. Or that? MSVC simply compiles it with the following warning:

warning C4250: 'D': inherits 'B :: B :: f' through dominance

Honestly, I've never met the term "dominance" before. When I look for it in the standard, it has one occurrence in the index and refers to the chapter where my first quote comes from. And, as I mentioned, the quote seems to refer only to hiding the name, not to redefining virtual functions.

Questions:

  • Does f more than one finite override in D?
  • In this case, the rule of domination applies? How does this follow from the standard?
+6
source share
1 answer

I quote again [10.3]/2 :

The virtual member function C::vf object of class S is a finite redefinition, if only the most derived class (1.8), from which S is a subobject of the base class (if any), declares or inherits another member function, redefines vf . In a derived class, if the virtual function-member subobject of the base class has more than one final override, the program is poorly formed.

So, in your example, A::f not the final redefinition, because D (the most derived class) inherits B::f , which overrides it. B::f is the final redefinition, and therefore it is called.

A program would be poorly formed if there were more than one final override (for example, if C also overrides f ), but there is only one, so everything is fine.

Clang and GCC compile this without warning .

Answering your question, the C4250 warning documentation describes exactly your situation, and in terms of dominance, this apparently means the behavior described in [10.3]/2 .

+5
source

Source: https://habr.com/ru/post/978003/


All Articles