这是一个例子,我试图理解非限定名称如何查找重载声明的工作:
int foo(char a){ return 0; }
namespace A
{
int foo(int a){ return a; }
int foo(){ return 2; }
extern int j;
extern int i;
}
int A::j=foo('a'); //97
int A::i=foo(); //2
这意味着找不到通过非限定名称查找的int foo(char);
,但可以找到int foo(int);
和int foo()
。因此,我认为只要找到名称的所有重载声明,非限定名称就会查找重载声明结束。我无法找到标准,我只能找到以下内容(秒。 3.4.1):
只要找到名称的声明,名称查找就会结束。
这句话没有说明重载声明的查询。
答案 0 :(得分:2)
您将名称查找与重载决策混合在一起。没有"不合格的名称会查找重载的声明"。名称查找和重载解析是分开的。
名称查找意味着确定找到名称的范围。完成后,重载决议确定应该使用该范围中可见的哪些声明。< / p>
在您的代码中,名称查找确定foo
表示A::foo
。然后重载决策在A::foo()
和A::foo(int)
之间进行选择。 ::foo
不考虑重载解析,因为它不是A::foo
的定义。
另一个例子:
namespace C { void f(); }
namespace B { void f(); void f(float); }
namespace C { void f(long); }
using namespace C;
int main()
{
f(1.0);
}
处理行f(1.0)
时,名称查找会看到void f();
并停止。结果是f
表示C::f
。
然后重载决策启动,C::f
的所有声明都被认为是重载解析。选择void f(long)
。
答案 1 :(得分:1)
在 declarator-id 是 qualified-id 的声明中,声明 qualified-id 之前使用的名称 在定义的命名空间范围中查找;在范围内查找 qualified-id 后面的名称 成员的类或命名空间。
(C ++11§3.4.3/ 3)
所以
int A::j=foo('a');
int A::i=foo();
在foo
范围内查找名称A
只是因为您在声明者的左侧有A::j
和A::i
。
请注意,如果你这样做
int k = foo();
只会找到全局foo
,您将收到错误。
答案 2 :(得分:0)
你说
中提出了类似的问题这意味着找不到通过非限定名称查找的
int foo(char);
,但可以找到int foo(int);
和int foo()
。因此,我认为只要找到名称的所有重载声明,非限定名称就会查找重载的声明。
从3.4.1 / 14开始:
如果命名空间的变量成员在其命名空间的范围之外定义,那么查找成员定义中出现的任何名称(在declarator-id之后),就好像该成员的定义发生在其命名空间。
您发布的代码相当于:
int foo(char a){ return 0; }
namespace A
{
int foo(int a){ return a; }
int foo(){ return 2; }
extern int j;
extern int i;
}
namespace A
{
int j=foo('a');
int i=foo();
}
当定义和初始化放在命名空间下时,很明显为什么首先在命名空间A
中查找用于初始化变量的函数。如果可以为命名空间A
中的函数找到明确的匹配,则搜索它将停止。这意味着,在编译行时,
int A::j=foo('a');
foo
的查找从名称空间A
开始,已解析为int A::foo(int);
,搜索foo
停止。
希望这可以解决这个困惑。
答案 3 :(得分:-1)
在标准(§3.4/ 1)
中名称查找应 找到一个明确的名称声明(见10.2)。如果名称查找名称是函数名称,则名称查找可以将多个声明与名称相关联;据说声明形成一套 重载函数(13.1)。名称查找成功后,将发生重载分辨率(13.3)。 访问规则(第11条)仅被视为名称查找和函数重载解析(如果 适用)已成功。
这意味着方法的步骤如下:
对于方法,在找到第一个匹配后,名称查找不会返回,而是搜索所有匹配的名称。从语句中可以清楚地看到,如果名称查找的名称是函数名称 ,则名称查找可能会将多个声明与名称相关联。