c – 名称查找中的重载分辨率/歧义(哪一个)

$7.3.3 / 14(C 03)

struct A { int x(); };
struct B : A { };
struct C : A {
   using A::x;
   int x(int);
};
struct D : B, C {
   using C::x;
   int x(double);
};
int f(D* d) {
   return d->x(); // ambiguous: B::x or C::x
}

‘f’中代码中的注释表示可以预期’B :: x’或’C :: x’之间存在歧义.

但是,在使用g(ideone)或Comeau进行编译时,错误会略有不同.这些错误而不是指示B :: x或C :: x中的歧义表明A是D的模糊基数这一事实

prog.cpp: In function ‘int f(D*)’:
prog.cpp:16: error: ‘A’ is an
ambiguous base of ‘D’

“ComeauTest.c”, line 21: error: base
class “A” is ambiguous
return d->x(); // ambiguous: B::x or C::x

按照$10.2中的名称查找规则,我觉得代码片段中的注释不是真的正确.该错误确实首先与基类“A”的模糊性有关,而不是与其他任何事物有关(例如,重载决策中的模糊性).有什么想法吗?

最佳答案 这是由于C 03中的名称查找扭曲引起的:检查一个明确的子对象是C 03中类成员名称查找的一部分.C 03中的查找将找到D :: X和C :: x以及A :: x ,其中A :: x匹配,但与A类型的两个不同子对象相关联.

在C 0x中,检查明确的子对象现在是相应子条款的一部分,参见DR #39:x直接成为其成员的类是一个不明确的基础 – 所以第5条将导致编译错误,而不是第10条.

请注意,该注释讨论了A的子对象.A的一个子对象遍历路径B,另一个子对象A遍历路径C.这就是注释“B :: x或C :: x”的原因”.可以通过仅尝试转换为其类类型来确定相同类类型的多个子对象的存在,忽略可访问性问题:如果转换不明确,则子对象出现多次.

点赞