0

I have a problem with inheriatance. Say i have 4 classes: base class A, class B inheriates A, class C inheriates A, class BC inheriates B and C

class A
{
    public:
        void test()
        {

        }
};

class B :public A
{
};

class C :public A
{
};

class BC :public B,public C
{

};

int main()
{
    BC a;
    a.test();
}

Result:

In function ‘int main()’:
error: request for member ‘test’ is ambiguous
note: candidates are: void A::test()
note:                 void A::test()

How can i fix this ? Is this even possible ? What i want is a single instance of all three classes in BC.

Greetings, Thalhammer

Thalhammer
  • 285
  • 3
  • 7
  • 3
    http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem . For `what i want is a single instance of all three classes`, read about a virtual base class. – Igor Tandetnik Aug 22 '14 at 22:52
  • Do you want an instance of the classes *in* BC? In that case, you should probably make them members instead of using inheritance. – E. Moffat Aug 22 '14 at 22:54
  • Could you please just say "struct" and remove those thousands of noisy and pointless `public`s? – Kerrek SB Aug 22 '14 at 22:55

3 Answers3

1

See section 25 on C++ FAQ, with attention to question 25.8.

If you want for class BC to derive just once from class A, you should declare classes B and C to have virtual inheritance from A:

class A {};
class B : public virtual A {};
class C : public virtual A {};
class BC : public B, public C {};
André Sassi
  • 1,076
  • 10
  • 15
0

The object a has two subobjects of type A, one contained in its B base subobject, and one contained in its C base subobject. To select which one you want to call, add an intermediate cast:

BC a;

static_cast<B &>(a).test();
static_cast<C &>(a).test();
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

You've just discovered The Diamond Problem:

Concisely put, non-virtual inheritance implies the creation of a unique base class subobject for each class that inherits from a class. Both B and C inherit from A so that means that they both contain a separate unique A subobject. When BC finally inherits from B and C, it will have four subobjects in total: B::A, C::A, B, and C.

Calling BC::test causes a name lookup for the member test. Because BC has two A subobjects, the result is an ambiguous call because both functions are viable.

Virtual inheritance means that a single base class subobject will be shared amongst every deriving class. A virtual base class is a class that is virtually inherited from. Use the virtual specifier to make this work:

struct A { };
struct B : virtual A { };
struct C : virtual A { };
struct BC : B, C { };

Now that BC has only one A subobject, the call to BC::test will be unambiguous because it is clear to the compiler that that test only resides in a single A.

David G
  • 94,763
  • 41
  • 167
  • 253