C++ 多路径继承:为什么使用 Base class 作用域的访问是明确的?

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

我正在学习C++,在学习虚继承的过程中遇到了以下疑惑:

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 
 }

在行 cout << d.A::x; 它打印 5。这个调用不应该是模棱两可的吗?如果不是,为什么它打印 5?

d.A::x;确实有歧义。 GCC 和 Clang 将其报告为错误,只有 MSCV 没有这样做:https://godbolt.org/z/1zhjdE6a8.

[class.mi] 中有一个注释,其中有一个多重继承的例子,指出:

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]

这只是一个注释,因为它遵循 [class.member.lookup](阅读和理解起来有点做作)没有限定符,成员访问是不明确的。 “格式错误”意味着符合标准的编译器必须发出错误或警告。

根据 GCC 和 Clang,这是不明确的,但 MSVC 编译了它 (Godbolt)

如果在 D 中只有一个 A 实例有意义,您可以通过对 BC 使用虚拟继承来解决它,或者您可以指定调用必须通过哪个父级访问 A::x 如果您需要 D 中 A 的两个不同实例。

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

以上在所有 3 个编译器上编译都没有错误,因为它是明确的。它指定通过哪个中间class访问A::x