Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Virtual Inheritance of virtual method

struct A {
    virtual void foo() { std::cout << "a";};
};

struct B:public virtual A {
    void foo() { std::cout << "b";}
};

struct C:public virtual A {
    void foo() { std::cout << "c";}
};

struct D:public B, public C {

};
int main() {
    return 0;
}

So this one while compiling gives us the following error:

 \main.cpp:16:8: error: no unique final overrider for 'virtual void A::foo()' in 'D'
 struct D:public B, public C {

If we would make the inheritance of B and C structs non-virtual, the code is compiling just right without any errors (but of course the error happens if we're calling dd.foo()). So what's the difference? Why do we have an error when we inherit our class virtually and no error if we do it straight?

like image 441
Utikeev Avatar asked Sep 27 '22 13:09

Utikeev


1 Answers

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.

like image 128
chris Avatar answered Sep 30 '22 07:09

chris