2010-07-05 111 views
4

類請看下面的代碼:成員函數隱藏在派生

#include <iostream> 
using namespace std; 

class A { 
    public: 
    A() {};  
    virtual void foo(double d) { cout << d << endl; } 
    virtual void foo(double d, int a) = 0; 
    }; 

class B : public A { 
    public: 
    B() {}; 
    virtual void foo(double d, int a) { cout << d << endl << a << endl; } 
    }; 

int main() 
    { 
    B b; 
    b.foo(3.14); 
    return 0; 
    } 

編譯器(試過G ++和Visual C++ 2008)說,有沒有像B無功能:FOO(雙)。 G ++的確切消息是:

main.cpp:21: error: no matching function for call to ‘B::foo(double)’

它看起來像hiding rule的效果,但在我看來,規則不應該用在這裏,因爲我不重寫富(雙)和兩個FOO方法定義在基類中。

我知道我可以在派生類B.

你能解釋一下爲什麼代碼不編譯和C的哪些規則++適用於這裏與

using A::foo; 

聲明解決這一問題?

+1

這只是「名稱隱藏」問題。爲什麼你不能只使用'使用A :: foo'子句? – ereOn 2010-07-05 07:56:04

+0

不是一個確切的重複,但在這裏討論相同的問題:http://stackoverflow.com/questions/72010/c-overload-resolution – ereOn 2010-07-05 08:00:12

+0

在這種情況下,如果你想實現你的純虛擬富方法你必須重新定義所有的方法名稱「foo」或爲純虛擬方法和實施方法選擇不同的名稱。 – Sergey 2010-07-05 08:56:36

回答

4

隱藏規則不是重寫,而是隱藏名稱。如果派生類聲明瞭一個成員函數,則會隱藏具有相同名稱的其他基類成員函數。這也發生在你的情況。

1

對我來說看起來完全合理。雖然函數簽名對於知道函數是什麼很重要,但我可以看到這種行爲如何防止非常愚蠢的錯誤。

正如ereOn建議的那樣,使用指令是一個公平的支付價格。

+0

+1:如果你想了解更多,你可以看看http://becomeaprogrammerin21years.blogspot.com/2008/03/c-inheritance-oddity.html – ereOn 2010-07-05 08:02:12

5

名稱陰影,而不是特定的功能。一旦在B中製作foo,則所有基本foo(注意,按名稱!)都會被遮蔽。

2

當編譯器遇到一個標識符時,查找規則就會啓動並開始搜索該標識符。在具體情況下,編譯器知道foo必須是B或其子類之一的成員。查找規則指出,編譯器必須從大多數派生類(考慮對象的靜態類型)開始並在層次結構中進行跟蹤,一旦在一個級別中找到標識符,將只考慮該級別的定義,不能繼續向上看。不管什麼f回報

B& f(); // might return a B or something derived from B 
void test() { 
    B& b = f(); // static type is B 
    b.foo(1.0); 
} 

,靜態類型是B,所以編譯器將在B類查找和發現B::foo(double,int)。由於該級別沒有其他foo聲明,因此編譯器必須嘗試將函數調用與可用的方法聲明進行匹配(並使其失敗)。

重要的是,查找不看對象,而是看起來按類型和向上,只要遇到第一個實例切割。