2013-03-16 105 views
5

C++代碼如下:我可以在繼承中只覆蓋一種方法嗎?

#include<iostream> 
using namespace std; 

class A 
{ 
    public: 
     virtual void f(int i) 
     { 
      cout << "A's f(int)!" << endl; 
     } 
     void f(int i, int j) 
     { 
      cout << "A's f(int, int)!" << endl; 
     } 
}; 

class B : public A 
{ 
    public: 
     virtual void f(int i) 
     { 
      cout << "B's f(int)!" << endl; 
     } 
}; 

int main() 
{ 
    B b; 
    b.f(1,2); 
    return 0; 
} 

在編譯過程中,我得到:

g++ -std=c++11 file.cpp 
file.cpp: In function ‘int main()’: 
file.cpp:29:9: error: no matching function for call to ‘B::f(int, int)’ 
file.cpp:29:9: note: candidate is: 
file.cpp:20:16: note: virtual void B::f(int) 
file.cpp:20:16: note: candidate expects 1 argument, 2 provided 

當我嘗試後B的F(INT)使用覆蓋,我得到了同樣的錯誤。

是否有可能在C++中只覆蓋1個方法?我一直在尋找使用override的代碼示例,這些代碼將在我的機器上編譯並且還沒有找到。

+0

[虛方法導致派生類中的編譯錯誤]的可能重複(http://stackoverflow.com/questions/7274723/virtual-method-causes-compilation-error-in-derived-class) – 2013-03-16 15:37:17

+1

不,對不起,那是另一個問題。 – 2013-03-16 15:38:27

+0

[C++:隱藏規則背後的基本原理]的可能重複(http://stackoverflow.com/questions/4837399/c-rationale-behind-hiding-rule) – Angew 2013-03-16 15:50:15

回答

5

您正在覆蓋名稱「f」作爲方法名稱。所以任何超載也會被覆蓋。

您可以使用using關鍵字,只是告訴編譯器在基類看起來還有:

class B : public A 
{ 
    public: 
     using A::f; 
     virtual void f(int i) 
     { 
      cout << "B's f(int)!" << endl; 
     } 
}; 
10

的問題是,你的虛函數f()B類隱藏A的非虛擬超載具有相同名稱。您可以使用using聲明,使其範圍:

class B : public A 
{ 
    public: 
     using A::f; 
    // ^^^^^^^^^^^ 

     virtual void f(int i) 
     { 
      cout << "B's f(int)!" << endl; 
     } 
}; 
0

是的,它可以覆蓋只有一個類的方法,使虛擬的。當在繼承類中聲明時,非虛擬會被遮蔽。

4

你正由名稱查找用C如何工作++咬傷。編譯器搜索連續的範圍,直到它找到至少有一個名稱匹配的項目的範圍。

假設item是一個函數,然後它在具有該範圍內找到的那個名稱的函數中進行重載解析。如果這些都不起作用,它不會而不是繼續搜索更多範圍以找到更適合。

你可以,但是,得到它的搜索父類在這種情況下:

class B : public A 
{ 
    public: 
     using A::f; 
     virtual void f(int i) 
     { 
      cout << "B's f(int)!" << endl; 
     } 
}; 

乍一看,這似乎會using聲明可能會產生歧義。例如,using A::f;現在有兩個f(int)功能在B的範圍內可見(A::f(int)B::f(int))。C++也有一些規則可以解決這個問題,所以如果你在mainusing A::f;)的地方添加(例如)b.f(3);,你仍然不會產生歧義 - 它會像你期望的那樣叫b::f(int)