2011-09-01 46 views
2

考慮下面的代碼:虛方法會導致編譯錯誤,在派生類

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    virtual int f() {cout <<"A:: f()\n"; return 1;} 
    virtual void f(int) {cout <<"A:: f(int)\n";} 
    virtual void g() {cout <<"A::g()\n";} 
}; 

class B3 : public A 
{ 
public: 
    void f() {cout <<"B3::f()\n";} 
}; 

int main() 
{ 
    return 0; 
} 

它產生以下錯誤:

..\main.cpp:17: error: conflicting return type specified for 'virtual void B3::f()' 
..\main.cpp:9: error: overriding 'virtual int A::f()' 

但爲什麼呢?在最壞的情況下,我以爲我有一個隱藏的情況下,而是我得到關於的virtual int f() {cout <<"A:: f()\n"; return 1;}

感謝編譯錯誤,羅南

回答

0

不要混淆隱藏覆蓋。你重寫虛擬。

您的類定義等同於:

class B3 : public A 
{ 
public: 
    virtual void f() {cout <<"B3::f()\n";} 
}; 

一旦函數聲明爲虛,它仍將虛擬從基類派生的類,不管你是否明確聲明它虛擬的或沒有。因此,您試圖覆蓋虛函數並更改其返回類型,這在C++中是非法的。如果該函數不是虛擬的,那麼您只需隱藏基類實現,因此更改返回類型是有效的。不會有含糊之處,因爲編譯器會知道從哪裏調用該函數以及期望的返回類型。

然而,考慮有:

A* a; 
.... 
a->f(); 

什麼將A-F()返回? a是指向A的指針,但可指向B3類型的對象。所以它要麼返回一個int或不返回任何東西。看到這裏的含糊不清?

相反,沒有多態性參與,

A a; 
a.f(); 

將從CAL樓一樣b3.f會調用F從B3。總而言之,覆蓋基類函數意味着保持相同的返回類型。如果要創建具有不同返回類型的新函數,請更改其簽名(其名稱或參數 - 或兩者)。

無論如何,你甚至不應該這樣做......爲什麼你想要一個具有相同名稱的函數,沒有參數返回不同的東西?不會添加單獨的函數更具可讀性?

0

如果f()會有不同的參數列表,或者沒有在基類中聲明爲虛擬,那麼您將隱藏起來。在前一種情況下,由於重載不會跨越繼承邊界,所以Af將被隱藏。但事實並非如此,因爲你在兩個類上都有f(),這隻在返回值上有所不同。返回值協方差是唯一允許的差異,並且由於情況並非如此(void不從int繼承),所以會出現錯誤。

+0

您不需要不同的參數列表來隱藏基本功能。 –

+0

@Luchian,是的,你也可以使用不同的常量來隱藏。這是你想到的嗎?有沒有其他的方法來隱藏虛擬功能? – eran

相關問題