当你调用一个函数的时候,到底调用的是哪个?其答案取决于“名称搜索”,但你肯定会发现其细节非常令人吃惊。
【问题】
在下面代码中,调用时哪个函数?为什么?分析一下:
namespace A
{
struct X;
struct Y;
void f(int);
void g(X);
};
namespace B
{
void f(int i)
{
f(i); //哪一个f()?
}
void g(A::X x)
{
g(x); //哪一个g() ?
}
void h(A::Y y)
{
h(y); //哪一个h() ?
}
};
【解答】:
1.上述注释中,f()调用的是它自己,并且无限递归方式。原因:在namespace B中,唯一可见的是f()是B::f()自身。
2.g()调用在A::g(X)和B::g(X)间有二义性。虽然和f()一样,B没有using指令A::g(X)来带入它的空间范围,你可能认为只有B::g(X)可选。但是还有一条补充规则:
Koenig Lookup(简化版):
如果你的函数提供了一个class类型的实参(此处为A::X类型的x),那么在名称搜索时,编译器将认为包含实参类型的命名空间中的同名函数为可选函数。
下面例子更加复杂些,但实质一样:
namespace NS
{
class T{};
void f(T);
};
NS::T parm;
int main()
{
f(parm); //调用NS::f
}
3.h(A::Y) 函数调用的是自己,也是无穷递归方式。
虽然B::h()也是使用了namespace A中的一个类型,但是这不影响名称搜索的结果。因为namespace A中没有符合h(A::Y)名称的函数。
总结:
namespace B中的代码被完全独立的namespace A中申明的函数影响了,虽然B简单的提及了一个A中找到的类型以外,没有干任何的事情,甚至连using都没有。这只是一个特例。