假设我们有这个代码,从一个单独的问题复制:
namespace x
{
void f()
{
}
class C
{
void f()
{
using x::f;
f(); // <==
}
};
}
指定行上的名称f
明确指代x::f
(至少根据gcc和clang)。在这种情况下,为什么x::f
优先于x::C::f
?两个名字都可见,这不应该是模棱两可的吗?
答案 0 :(得分:10)
因为using
声明会将x::f
带入f
的范围,该范围比C
的范围窄。非限定查找会考虑本地块范围,找到匹配项,并在考虑更广泛的类范围之前停止。由于没有函数参数,因此没有依赖于参数的查找,因此不会考虑其他范围。
答案 1 :(得分:7)
@ MikeSeymour的回答是现场的;这里是相关的标准引用(C ++ 11,强调我的):
13.3.1.1.1 / 3:
在非限定函数调用中,该名称不受
->
或.
运算符限定,并且具有更通用的形式 primary-expression。在正常规则之后的函数调用的上下文中查找名称 用于函数调用中的名称查找(3.4)。该查找找到的函数声明构成了一组 候选职能。 由于名称查找规则,候选函数集完全由(1)组成 非成员函数或(2)完全属于某个类T
的成员函数。 ......
3.4.1 / 1:
在3.4.1中列出的所有情况下,范围将按照每个中列出的顺序搜索声明 各自的类别;一旦找到名称的声明,名称查找就会结束。如果没有声明 发现,该计划格式不正确。
3.4.1 / 8
在函数的 declarator-id 之后定义类
X
的成员函数(9.3)的名称 ......应在其中一个中宣布 以下方式:
- 在使用它之前或在封闭块(6.3)或
中使用之前- 应该是类
X
的成员,或者是X
(10.2)的基类成员,或者- ...
从3.4.1 / 8开始,我们看到名称f
的声明(例如声明using x::f;
)在其使用的块中的列出早于f
作为班级C
的成员。根据3.4.1 / 1,选择较早的一个,因此整个查找解析为x::f
声明引入的using
。
答案 2 :(得分:1)
我认为C ++标准中的这些引用是相关的:
来自C ++标准(7.3.3使用声明)
13由于使用声明是声明,因此受到限制 同一声明区域中的同名声明(3.3) 也适用于使用声明。
和(3.3.7班级范围)
4)在成员函数中声明的名称隐藏了声明 范围扩展到或超过成员结尾的同名 功能的类。