2013-10-26 90 views
1
void f() 
{} 

struct A 
{ 
    void f() 
    {} 
}; 

struct B : A 
{ 
    B() 
    { 
     f(); // A::f() is always called, and ::f is always ignored 
    } 
}; 

int main() 
{ 
    B(); 
} 

由於類B的設計師,我可能不知道的事實,B的基類,即A,有一個成員函數A::f,我只知道::f,並呼籲::f正是我所想要的東西。爲什麼成員函數的重載決議排除全局函數?

我期望的是編譯器給出一個錯誤,因爲調用f含糊不清。但是,編譯器始終選擇A::f並忽略::f。我認爲這可能是一個很大的陷阱。

我只是想知道:

爲什麼成員函數的重載決議排除在全球的功能呢?

原因是什麼?

回答

4

由於B類的設計師,我可能不知道B的基類

我不同意。

爲什麼成員函數的重載分辨率不包括 全局函數?

因爲兩個重載屬於兩個不同的作用域,編譯器選擇相同作用域的重載。閱讀§3.4.1。內部(相同)範圍的f隱藏了外部的f

原理是什麼?

要有一個堅實的規則。我們更喜歡在相同的範圍內工作。除非我們明確地想從其他地方調用對象。

在一個叫亞歷克斯的家庭裏,他們期待他們的小男孩亞歷克斯進來,而不是Alexander III of Macedon

3

這就是重載分辨率是如何工作的,並且很好

想象一下,您確實有一個大項目,大量的相互依賴關係,第三方代碼和跨模塊包含在內。在這個巨大的混亂中,你有一個你認識的課程。它已經運行了5年,效率高,易於閱讀和清潔。你不想碰它。然後您升級模塊,並開始出現編譯器錯誤。不好了!該模塊(您無法控制)在全局名稱空間處引入了一個新功能DoAmazingStuff()。與我們班的方法名稱相同。您將不得不重構它,因爲現在您不能再爲類成員使用相同的名稱。壞消息!

+0

+1爲令人信服的情況。 – xmllmx

相關問題