1。符號查找(對于函數此時只看名字,不看參數)
??? 大致順序是
??? (1)如果有限定名( XXX:: )那么就直接在XXX里查找
??? (2)函數局部名字空間
??? (3)(如果是成員)類名字空間
??? (4)遞歸向上至所有基類的名字空間
??? (5)當前名字空間
??? (6)遞歸向外至所有外層名字空間,
??? 在任一層里, 用using導入的符號和該層的其他符號同一對待。
??? keonig查找: 對于函數, 如果參數為類/結構/模版類并位于其他的名字空間,
??? 在(5)和(6)的查找中導入該空間(不遞歸向外)的符號一同查找.
2。(如果是函數)重載決議(注意此時特化的函數不參與決議)
3。(如果是類內部的名字)檢查訪問權(注意此時特化的函數仍然不參與決議)
4。(如果找到了一個模版)模版特化決議
?
編譯器執行以上步驟的時候是使用貪心匹配,只要找到一個符合當前檢查內容的就會停止查
找
所以任何一層都有可能發生錯誤的掩蓋情況
例1
?1
void
?f(
int
)
{}
?2
class
?Y
?3
{
?4
public
:
?5
????
void
?f()
{}
?6
????Y()
?7
????
{
?8
????????f(
1
);
?9
????}
10
}
;
這里的f(2)在1.(2)這里找到了符號f,就不會向上到1.(5)查找到真正的f(int)了
例2
void
?g(
int
)
{}
namespace
?S

{

????
void
?g()
{}
????
void
?h()

????
{
????????g(
1
);
????}
}
這里的g(1)在1.(5)這里找到了符號g,就不會向上到1.(6)查找到真正的g(int)了
例3
class
?Y

{

????
void
?f(
int
)
{}
?
//
[1]
public
:

????
void
?f(
double
)
{}
?
//
[2]
}
;

int
?main()

{
????Y?y;
????y.f(
1
);
}
y.f(1)會調用[2]嗎?不會,因為在第2步重載決議的時候就選定[1]了,因此這段代碼會報
出無法訪問private成員的錯誤
例4
template?
<
typename?T
>
void
?f(T)
{}
?
//
[1]
template?
<
typename?T
>
void
?f(T
*
)
{}
?
//
[2]
template?
<>
void
?f
<
int
*>
(
int
*
)
{}
?
//
[3]
int
?main()

{
????
int
?
*
p?
=
?
0
;
????f(p);
}
這里的f(p)會調用[3]嗎?
不會,因為在進行到第二步重載決議的時候,只有[1]和[2]參與了重載決議,結果選擇了
[2],那么[1]的特化版本[3]當然就輪不到了。
例5
class
?X

{

????template?
<
typename?T
>
?
void
?g()?
{}
public
:

????template?
<>
?
void
?g
<
int
>
()
{}
}
;

int
?main()

{
????X?y;
????y.g
<
int
>
();
}
這里首先第3步訪問檢查發現g為private(此時g的特化版本被直接無視了),所以即使
g<int>為public, 該段代碼仍然不能夠編譯通過
例6
namespace
?E

{

????
class
?X
{}
;

????
void
?f(X)
{}
?
//
[1]
}
void
?f(E::X)
{}
??
//
[2]
class
?X

{
public
:

????
void
?f()
{}
?
//
[3]
????
void
?g()

????
{
????????E::X?x;
????????f(x);?
//
[4]
????}
}
;

[4]會調用那個呢? 在1.(3)里就確定了是[3],因此參數不匹配
如果注釋掉[3]的f,那么由于koenig查找, 在1.(5)里[1]和[2]都會是平等的可選項
所以會出現二義性.
如果把namespace E改為class E, 把E中的f改為靜態函數
由于koenig查找僅僅導入參數的名字空間, 因此[1]將不參與1.(5)的查找,
最終結果會是[2]