答案是铛是正确的。但是,根据标准,代码也可能会失败。
如果你看看11.2p5它有一个相关的说明(是的,我知道笔记非规范):
[注:这个类可以是明确的,例如,当一个合格的-ID是使用, 或隐式,例如,当使用类成员访问运算符(5.2.5)时 (包括添加了隐含“this->”的情况)。 如果012xx成员访问运算符和合格ID都用于命名成员 (如p->T::m
中所示),则命名该成员的类是由 指定的类。qualified-id的嵌套名称说明符即T)。末端注意 ]
这是什么意思音符,是,如果你然后添加到this->
C::x = 2;
C
是类命名的成员和gcc 4.7.2 correctly fails when this is the case。
现在的问题是谁是为C::x
命名成员的班级? 该naming class
由相同11.2p5
指定:由类
到成员的接入会受到影响,其中所述构件是 命名。 这个命名类是查找并找到成员名称为 的类。
现在,类成员名称查找在10.2指定,阅读这一切后,我的结论是x
是子对象集工会按:
否则,新的S(f,C)是一个查找集,其中共享集 声明和子对象集的联合。
这意味着根据构件查找规则x
可以是从B
或A
!这使得代码不良形成:Name lookup can result in an ambiguity, in which case the program is ill-formed.
然而,这种不确定性可以被解析为每10.2p8:
歧义往往可以通过与同级车 名排位赛的名称来解决。
而且从Clang source,我们可以看到这是他们选择这样做:
// If the member was a qualified name and the qualified referred to a
// specific base subobject type, we'll cast to that intermediate type
// first and then to the object in which the member is declared. That allows
// one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as:
//
// class Base { public: int x; };
// class Derived1 : public Base { };
// class Derived2 : public Base { };
// class VeryDerived : public Derived1, public Derived2 { void f(); };
// void VeryDerived::f() {
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
但是,请注意上述报价的措辞can
:often can be resolved
。这意味着他们不一定要解决。所以,我认为根据标准,代码应该失败,因为模糊或作为私人成员访问失败。
编辑
有关于can
解释一些竞争和是否一个歧义发生在这里。我发现Defect report 39. Conflicting ambiguity rules谈到了这个问题。
编译[有](http://ideone.com/clone/VvWyUW)(尽管同样的编译器)。似乎GCC的错误呢? – 2013-03-13 23:37:44
有趣的是:相同的编译器,不同的结果。无论如何,我无法想象任何东西 – 2013-03-13 23:39:34
g ++ 4.7.2成功地在两个位置编译相同的源代码。 – Aneri 2013-03-13 23:39:51