for*_*818 15 c++ multiple-inheritance qualified-name diamond-problem language-lawyer
MSVC, Clang and GCC disagree on this code:
struct Base { int x; };
struct Der1 : public Base {};
struct Der2 : public Base {};
struct AllDer : public Der1, public Der2 {
void foo() {
Der1::Base::x = 5;
}
};
Run Code Online (Sandbox Code Playgroud)
GCC:
<source>: In member function 'void AllDer::foo()':
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'
10 | Der1::Base::x = 5;
| ^
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
Clang gives a similar error, and MSVC gives no error.
Who is right here?
I suppose this is covered in [class.member.lookup], but I have difficulties understanding what it is trying to tell me for this case. Please quote the relevant parts and if possible explain in plain English.
PS: Inspired by this question Why is Reference to Base Class ambiguous with :: -operator trough derived class?
PPS: Actually my doubt is whether Der1::Base refers to the type, that would be Base (and then Der2::Base is exactly the same type), or to the subobject. I am convinced that it is the first, but if it is the latter then MSVC would be right.
要回答标题中的问题,是的,Derived1::Base引用了注入的类名[class.pre] Base等Derived2::Base。两者均指类::Base。
现在,如果Base有一个静态成员x,那么查找Base::x将是明确的。只有一个。
这个例子中的问题是它x是一个非静态成员,并且AllDer有两个这样的成员。您可以x通过指定一个只有一个成员的明确基类来消除这种访问的歧义。是一个明确的基类,它有一个成员,因此明确指定您指的是两个成员中的哪一个。too 只有一个成员,但它不是. 的每个实例都有两个类型为 的子对象。因此,在您的示例中是模棱两可的。由于只是 的另一个名称,因此这仍然不明确。AllDerxDerived1xDerived1::xxAllDerBasexAllDerAllDerBaseBase::xDerived1::BaseBase
[class.member.lookup] 指定x在嵌套名称说明符的上下文中查找,因此必须首先解析。我们确实在寻找Base::x,而不是Derived1::x,因为我们从解析Derived1::Baseas开始Base。这部分成功,只有一个有x在Base.注意12 [class.member.lookup]明确地告诉你,当有与多个同名的子对象的利用无歧义的名称查找可能仍会失败。D::i在那个例子中基本上是你的Base::x.
之所以可以将类名作为类的成员来引用,是因为cpp为方便使用而给它起了别名,就好像你using Base = ::Base;在Base里面写的一样。
\n您\xe2\x80\x99面临的问题Der1::Base是Base。
\n因此,当你写 时Der1::Base::x,它\xe2\x80\x99s 与 相同Base::x。
| 归档时间: |
|
| 查看次数: |
253 次 |
| 最近记录: |