Virtual Inheritance: Error: no unique final overrider
T

3

24

I know virtual inheritance is covered here before and before asking this question, I went through the detail of the virtual inheritance and went through the details of a similar problem like the followings:

multiple-diamond-inheritance-compiles-without-virtual-but-doesnt-with and why does GCC give me an error - final overrider

My problem is slightly different as I am not using pure virtual function and explicitly using virtual inheritance to have one unique base class. The hierarchy is as follows:

   base
    /\
   /  \
 der1 der2
   \  /
   der3

I know about the dreadful diamond on the derivation issue, and that's why I am using virtual inheritance.

#include <iostream>
class base
{
public :

    base()
    {
        std::cout<<"base()" << std::endl;
    }
    virtual void fun()
    {
        std::cout<<"base" << std::endl;
    }
};

class der1: virtual public base
{
public :
    void fun()
    {
        std::cout<<"der1" << std::endl;
    }
};

class der2 : virtual public base
{
public :
    void fun()
    {
        std::cout<<"der2" << std::endl;
    }
};

class der3 : public der1,public der2
{
    public :
    /*void fun()
    {
        std::cout<<"der3" << std::endl;
    }*/
    //if I took out the comment and the function 
    //is defined it compiles fine as expected
};

int main()
{
    base *p=new der3;
    //used scope operation explicitly to avoid ambiguity
    p->base::fun(); //here it complains about 'no unique final overrider for fun'
    return 0;
}

My understanding is since I am using virtual inheritance, there should only be one instance of the base, and using the scope operator, I can invoke without ambiguity the virtual fun function. The function is not pure virtual. If I do leave an implementation on the der3 class it is giving me a compiler error:

error: no unique final override for ‘virtual void base::fun()’ in ‘der3’

I can see how this issue works (final overrider). But mine doesn't. Is it getting confused between base::fun, der1::fun and der2::fun? Does the scope operator help in any way?

Any clue or help is appreciated. I am using g++ 4.6.3.

Tillage answered 3/6, 2014 at 2:28 Comment(1)
I know why the above fails but I actually have a further question which is why I can't just put using der1::fun in der 3 and for it to then work?Centime
D
15

The most-derived class has to provide an implementation of the virtual functions in the virtual base class - otherwise how would it provide that base class interface, given the intermediate classes (i.e. your der1 and der2) provide two alternatives already - which one should it call? You have to disambiguate the situation (i.e. with der3::fun()).

Sure you're not actually calling der3::fun() as you're explicitly requesting base::fun(), but that doesn't mean the rules don't apply, any more than thinking you could instantiate an abstract class if you don't try to call the pure-virtual functions.... The program is ill-formed until the code ties off these loose ends.

Demasculinize answered 3/6, 2014 at 2:42 Comment(2)
Thanks @Tony D so the bottom line is to have only one final overrider.Tillage
@jazaman: yes, per C++11 Standard 10.3/2 "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."Demasculinize
P
10

Using the scope resolution operator to specify that you want to call base::fun doesn't make the error go away because the program would be ill-formed even with an empty main(). You simply are not allowed to have a situation in which a virtual function has more than one final overrider in any derived class that exists in your program.

Informally, just because trying to call p->fun() would be ambiguous, the program is ill-formed even if you don't do it.

Note: This is in contrast to the situation you have with overloaded functions, in which potential ambiguity is allowed---perhaps even unavoidable---as long as you avoid a call that actually would be ambiguous. Why are the rules different? Basically it is because even constructing an object of type der3 cannot be done in a sensible way---which version of fun should the vtable point to?

Paluas answered 3/6, 2014 at 2:47 Comment(1)
Thanks @Brian, Got that from the other answer. Do you have a standard reference about the final overrider?Tillage
M
0

Because you have virtual inheritance, the object of type der3 will only inherit one instance of base, i.e., it will not have two copies of base as it would without virtual inheritance. This means that der3 can only have one fun() method. If the fun() method were not virtual then you would have copies of this method.

Since in your case there can be only one fun() method, inheriting two versions causes ambiguity. You either have to remove one of the der1 or der2 overrides of fun(), in order to resolve the ambiguity (der3 will then inherit the one that is left), or you have to provide der3's own version.

Myosin answered 13/3 at 16:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.