Derived1 :: Base和Derived2 :: Base是否引用相同的类型? [英] Do Derived1::Base and Derived2::Base refer to the same type?

查看:226
本文介绍了Derived1 :: Base和Derived2 :: Base是否引用相同的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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;
    }
};

Godbolt

海湾合作委员会:

<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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆