Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is dominance in the context of virtual functions?

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?
like image 688
Armen Tsirunyan Avatar asked Nov 10 '14 22:11

Armen Tsirunyan


People also ask

In which context are virtual functions used?

When we talk about virtual function or virtual method, it's always in the context of inheritance and polymorphism. It is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature.

What is the function of virtual function?

A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.

What is polymorphism explain virtual function with example?

Virtual functions in C++ use to create a list of base class pointers and call methods of any of the derived classes without even knowing kind of derived class object. Virtual functions are resolved late, at runtime. The main use of virtual function is to achieve Runtime Polymorphism.

What is virtual function explain characteristics of it?

A virtual function is a member function of a class, whose functionality can be overridden in its derived classes. It is one that is declared as virtual in the base class using the virtual key word. The function body of base class can be completely replaced with a new set of implementation in the derived class.


1 Answers

I'll quote [10.3]/2 again:

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.

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

The program would be ill-formed if there were more than one final overrider (for example if C also overrode f), but there is only one, so everything is fine.

Clang and GCC compile this without a single warning.

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

like image 50
Anton Savin Avatar answered Sep 22 '22 01:09

Anton Savin