Home > OS >  C Multipath Inheritance : Why the access using Base class scope is non-ambiguous?
C Multipath Inheritance : Why the access using Base class scope is non-ambiguous?

Time:11-16

I am studying C and while studying virtual inheritance, I came across following doubt:

class A {
public:
    int x;
    A() { x = 677; }
    A(int a) { 
        cout << "A con , x= " << a << endl;
        x = a;
    }
};
class B : public A {
public:
    B(int a) : A(a) { }
};
class C :public A {
public:
    C(int a) : A(a) { }
};
class D : public B, public C {
public:
    D(int a,int b) : B(a),C(b) { }
};
int main()
{
    D d(5,6);
    cout << d.A::x;  //prints 5 
 }

In line cout << d.A::x; It prints 5. Shouldn't this call be ambiguous and if not why it prints 5?

CodePudding user response:

d.A::x; is indeed ambiguous. GCC and Clang report it as error, only MSCV fails to do so: https://godbolt.org/z/1zhjdE6a8.

There is a note in [class.mi] with an example of multiple inheritance stating that:

In such lattices, explicit qualification can be used to specify which subobject is meant. The body of function C​::​f can refer to the member next of each L subobject:

void C::f() { A::next = B::next; }      // well-formed

Without the A​::​ or B​::​ qualifiers, the definition of C​::​f above would be ill-formed because of ambiguity ([class.member.lookup]). — end note]

It is just a note, because it follows from [class.member.lookup] (which is a little more contrived to read and understand) that without the qualifier the member access is ambiguous. "ill-formed" implies that a conforming compiler must issue either an error or warning.

CodePudding user response:

This is ambiguous according to both GCC and Clang, but MSVC compiles it (Godbolt)

You can solve it by using virtual inheritance for B and C if it makes sense to only have one instance of A in D or you can specify via which parent the call must access A::x if you need two distinct instances of A in D.

std::cout << d.B::x; // go through B to its A
std::cout << d.C::x; // go through C to its A

The above compiles on all 3 compilers without error, because it is unambiguous. It specifies through which intermediate class to access A::x.

  • Related