2010-11-10 96 views
20

我有以下類別:爲什麼虛擬功能會隱藏?

class A { 
public: 
    virtual void f() {} 
}; 


class B : public A{ 
public: 
    void f(int x) {} 
}; 

如果我說

B *b = new B(); 
b->f(); 

編譯器錯誤說C2660: 'B :: F':函數不接受0參數。 B中的函數不應該重載它,因爲它是一個虛函數?虛擬功能是否隱藏起來?

編輯:我確實打算從A繼承B,B顯示了相同的行爲。

+9

也許你想得出''從A' B' 「這是使用using聲明輕鬆完成」? – 2010-11-10 16:17:48

回答

35

假設你打算從BA得出:

f(int)f()是不同的簽名,因此不同的功能。

您可以覆蓋具有兼容簽名的函數的虛擬函數,這意味着要麼是相同的簽名,要麼是返回類型是「更具體」(這是協方差)的函數。就像其他派生類聲明具有與基類函數同名的函數的情況一樣,派生類函數隱藏虛函數。您可以將using A::f;放在B類中以取消隱藏名稱

或者,您可以將其稱爲(static_cast<A*>(b))->f();b->A::f();。不同的是,如果B實際上確實覆蓋了f(),則前者調用覆蓋,而後者則調用A中的函數。

+0

澄清它!我不知道爲什麼我認爲使用'虛擬'時不應該發生隱藏。 但我現在看到它。謝謝:) – Oszkar 2010-11-11 07:15:06

+0

爲什麼我們無法隱藏不同返回類型的虛函數?即使非虛函數允許不同的返回類型。 – UnKnown 2016-03-12 13:14:34

+0

@UnKnown:使用*非*虛函數,函數是完全獨立的; 'A * a = new B(); a.nonVirtualFunction()'將調用'A :: nonVirtualFunction',而不是'B :: nonVirtualFunction'。但是使用* virtual *函數,它會調用'B :: nonVirtualFunction',所以顯然'B :: nonVirtualFunction'必須至少與'A :: nonVirtualFunction'最低限度兼容。 – ruakh 2016-12-26 17:32:53

7

B類不從A派生,所以沒有函數F()存在。你大概的意思是:

class A { 
public: 
    virtual void f() {} 
}; 


class B : public A { 
public: 
    void f(int x) {} 
}; 

編輯:我錯過了實際功能隱藏。請參閱Steve Jessop的答案以獲得更全面的解釋。

+0

雖然看上去很好,但並不能解決問題(請參閱Steve Jessops的回答)。 – 2010-11-10 16:19:16

+0

像@SteveJessop這樣的LOL我跳上了簽名問題,甚至沒有注意到'B'不是來自'A'! +1 – wilhelmtell 2010-11-10 16:19:20

+0

@wilhelmtell:沒錯,我沒有注意到遺漏的遺傳,直到羅德指出它。 – 2010-11-10 16:22:43

2

B不從A派生,正確的聲明是:

class B : public A 
+0

是的,我忘了,謝謝。 – Oszkar 2010-11-11 07:12:41

2

當編譯器解析符號的方法不止一種,它必須選擇哪一個具有優先權,除非代碼告訴它,否則。你期望的是重載優先於重載。 (一遍又一遍,結束,aaaaack!對不起,被'淹沒了')。

此示例使B繼承了子類提供重載版本的虛擬方法。重載是使用相同方法名稱但不同簽名的同一類中的方法。由於B是A的一個子類,它重寫了f(),這意味着它不能同時也是一個超載。這就是它被隱藏的原因。

對於A類,聲明方法

virtual void f() {} 

虛擬意味着方法使用一組特定的不與你B的聲明一致的規則來解決。

B *b = new B(); 

通過創建「B」爲「B」的一個實例,編譯器沒有必要使用相同的名稱的方法的虛擬性質在「A」。

如果你已經宣佈 'B' 這樣

B *b = new A(); 

則呼叫B-> F();確實會通過使用虛擬分辨率來引用A中的方法。

+0

我忘了寫這種方式。我現在糾正了它。 – Oszkar 2010-11-11 07:13:02

4

分別是和是。如果你想超載行爲,你需要說

using A::f; 

在B.

+0

'B'不是從'A'派生的 – 2010-11-10 16:22:57

+1

確實,我錯過了那個:)但是,如果是這樣,那就是你需要做的。 – 2010-11-10 19:45:15

+0

是的,我的意思是推導它。謝謝! – Oszkar 2010-11-11 07:12:10