Search code examples
c++multiple-inheritancevirtual-inheritance

in solution of diamond problem, why we need to inherit grand parent class two time virtually?


In the code below, why do I have to inherit class A virtually in both classes B and C?

I have learned that first compiler finds targeted function in derived class. If it is not found in it, then compiler has to search in its base classes. So, if I virtually inherit only once (class A) then compiler should find targeted function (aa()) through only one path, i.e. D to C to A in below case.

If I inherit it only once then problem still remains.

#include <iostream.h>
using namespace std;


class A
{
public: 
    void aa() { cout<<"aa"<<endl; } 
};

class B: public virtual A
{  };

class C: public /*virtual*/ A
{  };

class D: public C,public B
{  };

int main()
{
    D d1;
    d1.aa();
    return 0;
}

I get this error:

Error : Member is ambiguous: 'A::aa' and 'A::aa' in function `main()`

Solution

  • One answer would be: just because. It's the rule. You have too. Period.

    If you want another rule, make up another language. Just try to do that if you dislike a rule in any programming language and get back to us, tell us what exact semantics you came up with.

    But a deeper answer is that it would make very little sense for virtual to contaminate non virtual stuff.

    Do you expect a non virtual member function to become virtual because some other function with the same signature is virtual in some other class, and they end up being two bases? This is a real question, in an imaginary language you would make up to fit your intuition:

    struct A {
       void f(); // non virtual!
    };
    
    struct AA : A {
       void f(); // non virtual, hides, does not override
    };
    
    struct B {
       virtual void f();
    };
    
    struct BB : B {
       void f(); // virtual overrider 
    };
    
    struct A {
       void f(); // non virtual!
    };
    
    struct AABB : AA, BB {
       // is AA::f() now virtual? what about A::f()?
    };
    

    If you don't expect virtualness in BB to alter the semantics of AA, then you have the general answer: writing virtual does not change the virtualness of any previously established virtualness.

    So all you have to accept is that virtualness is a property of inheritance, a one-to-one relation, between a derived class and its base. Inheritance is established as virtual or non virtual in any given class.