Derived1 :: Base和Derived2 :: Base是否引用相同的类型? [英] Do Derived1::Base and Derived2::Base refer to the same type?
问题描述
MSVC,Clang和GCC在此代码上意见不一致:
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;
}
};
海湾合作委员会:
<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
Clang给出了类似的错误,而MSVC没有给出错误.
Clang gives a similar error, and MSVC gives no error.
谁在这里?
我想这已包含在 [class.member.lookup] ,但对于这种情况要告诉我的内容,我有一些困难.请引用相关部分,并在可能的情况下以简明的英语进行解释.
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:受此问题启发为什么对基类的引用与:: -operator trough派生类不明确?
PS: Inspired by this question Why is Reference to Base Class ambiguous with :: -operator trough derived class?
PPS:实际上,我的怀疑是Der1::Base
是指类型,即Base
(然后Der2::Base
是完全相同的类型)还是子对象.我坚信这是第一个,但是如果是后者,那么MSVC是正确的.
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
引用了
To answer the question in the title, yes, Derived1::Base
references the injected-class-name [class.pre] Base
and so does Derived2::Base
. Both refer to the class ::Base
.
现在,如果Base
将具有 static 成员x
,则Base::x
的查找将是明确的.只有一个.
Now, if Base
would have a static member x
, then the lookup of Base::x
would be unambiguous. There's only one.
此示例中的问题是x
是非静态成员,并且AllDer
具有两个这样的成员.您可以通过指定AllDer
的明确基类(只有一个x
成员)来消除对x
的此类访问. Derived1
是明确的基类,并且具有一个x
成员,因此Derived1::x
明确指定AllDer
中的两个x
成员中的哪个. Base
也只有一个x
成员,但这并不是AllDer
的明确基础. AllDer
的每个实例都有两个Base
类型的子对象.因此,Base::x
在您的示例中是不明确的.而且由于Derived1::Base
只是Base
的别称,因此仍然模棱两可.
The problem in this example is that x
is a non-static member, and AllDer
has two such members. You can disambiguate such access to x
by specifying an unambiguous base class of AllDer
which has only one x
member. Derived1
is an unambiguous base class, and it has one x
member, so Derived1::x
unambiguously specifies which of the two x
members in AllDer
you mean. Base
too has only one x
member, but it is not an unambiguous base of AllDer
. Every instance of AllDer
has two sub-objects of type Base
. Therefore Base::x
is ambiguous in your example. And since Derived1::Base
is just another name for Base
, this remains ambiguous.
[class.member.lookup]指定在嵌套名称说明符的上下文中查找x
,因此必须首先对其进行解析.我们确实在寻找Base::x
,而不是Derived1::x
,因为我们首先将Derived1::Base
解析为Base
.
这部分成功了,在Base.
中只有一个x
.[class.member.lookup]中的注释12明确告诉您,当存在多个具有相同名称的子对象时,使用明确的名称查找可能仍然会失败.在该示例中,D::i
基本上是您的Base::x
.
[class.member.lookup] specifies that x
is looked up in the context of the nested-name-specifier, so that has to be resolved first. We are indeed looking for Base::x
, not Derived1::x
, because we started by resolving Derived1::Base
as Base
.
This part succeeds, there's only one x
in Base.
Note 12 in [class.member.lookup] explicitly tells you that an using an unambiguous name lookup may still fail when there are multiple subobjects with that same name. D::i
in that example is basically your Base::x
.
这篇关于Derived1 :: Base和Derived2 :: Base是否引用相同的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!