Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using multiple inheritance, why is this qualified name ambiguous?

I'm trying to access the member variable x in struct Top using a Bottom object.

The code is the following:

#include <cstdio>

struct Top
{
public:
    int x = 1;
};

struct Left : public Top
{
    int x = 2;
};

struct Right : public Top
{
    int x = 3;
};

struct Bottom : public Left, public Right
{
    int x = 4;
}; 

int main()
{
    Bottom b;
    std::printf("value: %d\n", b.Left::Top::x);
    return 0;
}

This gives the following error using gcc 4.8:

main.cpp: In function 'int main()':
main.cpp:27:45: error: 'Top' is an ambiguous base of 'Bottom'
std::printf("value: %d\n", b.Left::Top::x);
                                        ^

How is this ambiguous and how do I access it with a qualified name?

like image 984
anoncoder Avatar asked Sep 20 '14 19:09

anoncoder


People also ask

What is multiple inheritance?

Multiple inheritance is a feature of some object-oriented computer programming languages in which an object or class can inherit characteristics and features from more than one parent object or parent class.

What is a diamond class inheritance diagram?

A diamond class inheritance diagram. The " diamond problem " (sometimes referred to as the "Deadly Diamond of Death") is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C.

What languages support multiple inheritance in the IBM System Object Model?

Implementations. IBM System Object Model (SOM) runtime supports multiple inheritance, and any programming language targeting SOM can implement new SOM classes inherited from multiple bases. Some object-oriented languages, such as C#, and Ruby implement single inheritance, although protocols, or interfaces,...

How do I use multiple inheritance in JavaFX?

JavaFX Script in version 1.2 allows multiple inheritance through the use of mixins. In case of conflict, the compiler prohibits the direct usage of the ambiguous variable or function. Each inherited member can still be accessed by casting the object to the mixin of interest, e.g. (individual as Person).printInfo ();.


Video Answer


1 Answers

The problem is that C++ has no way to directly express the concept of "multiple-level" class members, such as "the member x of the Top subobject of Left". What Left::Top::x means is "the member x in the type denoted by Left::Top" - and the type denoted by Left::Top is exactly Top.

This is why you can write odd things like

int Left::* ptr = &Right::Top::x;

because the right hand side of the = is exactly equivalent to &Top::x, and a pointer-to-base-class-member is implicitly convertible to a pointer-to-derived-class-member. (The result of this conversion still refers to the member in the base-class subobject of the derived class.)

To disambiguate, you can either do something along the lines of static_cast<Left &>(b).Top::x or use a pointer-to-member - given int Left::* ptr = &Top::x;, b.*ptr will refer to the x in the Top subobject of the Left subobject of b.

like image 137
T.C. Avatar answered Oct 07 '22 01:10

T.C.