7

It recently came to my attention成員函數完全影子在課堂內部具有相同名稱的自由函數。完全意味着每個具有相同名稱的自由函數都不考慮重載分辨率。我可以理解爲什麼它與somwthing這樣做:爲什麼類成員函數使用相同的名字來映射自由函數?

void f(); 

struct S 
{ 
    void f(); 

    void g() 
    { 
     f(); // calls S::f instead of ::f 
    } 
}; 

其中函數具有相同的特徵,其只是自然的,因爲變量的作用域的工作方式相同。但是,爲什麼禁止unambigious調用其中免費功能具有不同的簽名是這樣的:

void f(); 

struct S 
{ 
    void f(int x); 

    void g() 
    { 
     f(); // fails to compile attempting to call S::f, which has wrong signature 
    } 
}; 

我不問如何調用從類中的陰影免費功能。我想知道的是這個設計背後的基本原理。

+1

您可能需要問問Bjarne Stroustrup! – peacemaker 2012-07-27 21:47:30

+1

像這樣搜索意味着生成的候選函數列表總是很小。這對於編譯時間很有用,你可以想象它是否搜索了所有可能的候選(包括ADL),並且有很多模板,它很快就會變得非常慢。它也反映了大多數情況下的使用情況和期望的語義。通常當你說'foo'時,你想到的'foo'是最接近的。如果它不是最接近的那個,它很可能只是犯了一個錯誤。一個錯誤比運行時發生的奇怪東西更好。保持本地事物是良好的行爲。 – Flexo 2012-07-27 21:48:34

+2

您可以在名稱查詢中欣賞此演示文稿:http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of -n – MFH 2012-07-27 21:50:07

回答

6

對於不合格的名稱查找,每次只考慮一個範圍,如果該範圍內的搜索沒有產生任何結果,則搜索下一個更高範圍。在你的情況下,只搜索S的範圍。

但爲什麼禁止unambigious調用其中免費功能具有不同的簽名是這樣的:

的問題是,名稱查找不與任何東西,但名關注自身的標識符。它完全沒有意識到你想調用一個函數,它只是看到一個標識符。如果您只是使用auto x = f;,則會發生同名查詢,如果您這麼想,那麼您只需要一個非常有限的搜索範圍就有很好的理由。其他任何事情都會讓用戶感到驚訝。

+1

「_問題是,名稱查找不關心任何東西,除了名稱和標識符。」幾乎在所有語言中,這都是事實。不在C++中。 – curiousguy 2012-08-16 17:51:14

2

我無法提供一個權威的答案(也許有些人記得Design and Evolution of C++的報價,或者當時實際上已經在委員會中),但是我的第一個猜測是在您展示的案例中完全失敗。很容易忘記在某個時間範圍內有多少事情。另外,重載解析可能非常複雜,並且可以有默認參數和轉換。所以我寧願在這種情況下的範圍最有限,以確保被調用的是什麼。

+0

猜測,但這也是我的預感。依靠瘋狂的遠距離搜索和拼寫錯誤很難區分。 – Flexo 2012-07-27 21:51:20

+0

「_很容易忘記在某個時間範圍內有多少事情。」這是一個非常有力的論點,因爲這裏不做名稱隱藏。 – curiousguy 2012-08-16 17:54:09

3

有一種特殊的,非常令人驚訝的,規則(但它並不適用於你的例子)指出,一旦類成員的名字由名稱查找發現,沒有命名空間範圍內搜尋:

#include <string> 

struct C { 
    std::string s; 

    explicit C (std::string); 

    void swap (C& rhs) { 
     swap (s, rhs.s); // error: swap is C::swap 
    } 
}; 

void swap (C& lhs, C& rhs) { 
    swap (lhs.s, rhs.s); // std::swap(string,string) 
} 

海事組織,這是瘋狂。

但爲什麼禁止unambigious電話,其中免費的功能有不同的簽名是這樣的:重載決議之前

名稱查找發生:

  • 如果查詢是不明確的,超載的分辨率沒有這樣做。
  • 如果通過名稱查找找不到可行的函數,則不會嘗試其他輪查找。

規則是非常複雜沒有超載和姓名查詢之間的「反饋」。我會建議簡化(如刪除成員隱藏名稱空間作用域名稱規則,並刪除模糊的名稱查找),而不是複雜化。

+0

這並不像你想象的那麼瘋狂。如果找到匹配項(名稱約在§3.4左右),名稱查找將停止,並從內向外得到精確的順序。因此,如果找到具有名稱的成員,則會停止。沒有驚喜。 – Damon 2015-05-04 14:52:22

+0

@Damon「找到匹配時停止_Name查找_」不會,因爲我的第二個'swap'調用顯示 – curiousguy 2015-05-05 00:29:50