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 实例有意义,您可以通过对 B
和 C
使用虚拟继承来解决它,或者您可以指定调用必须通过哪个父级访问 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
。
我正在学习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::
orB::
qualifiers, the definition ofC::f
above would be ill-formed because of ambiguity ([class.member.lookup]). — end note]
这只是一个注释,因为它遵循 [class.member.lookup]
(阅读和理解起来有点做作)没有限定符,成员访问是不明确的。 “格式错误”意味着符合标准的编译器必须发出错误或警告。
根据 GCC 和 Clang,这是不明确的,但 MSVC 编译了它 (Godbolt)
如果在 D 中只有一个 A 实例有意义,您可以通过对 B
和 C
使用虚拟继承来解决它,或者您可以指定调用必须通过哪个父级访问 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
。