Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Inheritance Virtual Call Ambiguity

The problem at hand is hard to describe so the code is placed up front for better clarity.

struct Base
{
    int b;
    virtual void foo(){cout << b << endl;}
    Base(int x) : b(x){}
};

struct Derived1 : Base    //not virtual
{
    virtual void foo(){/*Derived2's code*/}
    Derived1() : Base(1){}
};

struct Derived2 : Base    //not virtual
{
    virtual void foo(){/*Derived2's code*/}
    Derived2() : Base(2){}
};

struct MultiInheritance : Derived1, Derived2
{
    void bar1()
    {
        //needs to access Derived1's Base foo()
    }
    void bar2()
    {
        //needs to access Derived2's Base foo()
    }
};

Suppose that in some weird bizarre scenario, I would want a base class MultiInheritance that has two base classes Derived1 and Derived2 that have a common non-virtual base class Base.

There are two Base in MultiInheritance, how do I specify which Base class I wish to access in MultiInheritance?

The code above seems to work fine by casting several times, but I'm not sure if this is defined behavior or not. If it is, how is this implemented by the compiler to fulfill the needs of polymorphism? On one hand virtual calls should all result in the same virtual function table, but on the other if it does it wouldn't output different answers.

EDIT

I wish to emphasize that the Base classes are required to be non-virtual

EDIT2

Deep apologies, I seriously misrepresented myself. The code above is updated better reflects my original question.

like image 682
Passer By Avatar asked Oct 31 '22 23:10

Passer By


1 Answers

This is known as the diamond problem.

http://www.cprogramming.com/tutorial/virtual_inheritance.html

If you want to keep base non-virtual and get the behavior you are seeking now, you can do this inside MultipleInheritance the following way to ensure you are calling the foo() function from the correct base class

struct MultiInheritance : Derived1, Derived2
{
    void bar1()
    {
       Derived1::foo();
    }
    void bar2()
    {
        Derived2::foo();
    }
};
like image 136
RyanP Avatar answered Nov 15 '22 04:11

RyanP