![](/img/trans.png)
[英]Overloading Virtual Functions with same arguments and different return types
[英]Virtual functions with different argument types
我試圖理解虛函數是如何工作的,我陷入了某個角色。
我寫過這個小程序:
class First
{
public:
virtual void f(int a)
{
cout << "First!" << endl;
cout << a << endl;
}
};
class Second : public First
{
public:
void f(int a) {
cout << "Second!" << endl;
cout << a << endl;
}
};
void main() {
Second s;
First *p = &s;
p->f(5);
First n;
p = &n;
p->f(3);
_getch();
}
此代碼導致:
Second! 5 First! 3
但是,如果我將Second::f()
函數中的int
更改為其他類型,如下所示:
class First
{
public:
virtual void f(int a) {
cout << "First!" << endl;
cout << a << endl;
}
};
class Second : public First
{
public:
void f(double a) { //double instead int here!
cout << "Second!" << endl;
cout << a << endl;
}
};
void main() {
Second s;
First *p = &s;
p->f(5);
First n;
p = &n;
p->f(3);
_getch();
}
我的程序從不調用Second::f()
,我得到的結果如下:
First! 5 First! 3
有人可以向我解釋為什么會這樣嗎?
當使用虛函數調度時,所謂的“最終覆蓋”就是被調用的東西。 對於甚至覆蓋繼承的虛函數的函數,它必須滿足一些條件:
如果虛擬成員函數
vf
在類Base
和Derived
類中聲明,直接或間接從Base
Derived
,則具有相同名稱的成員函數vf
, parameter-type-list (8.3.5),cv-qualification和聲明了Base::vf
refqualifier(或不存在),然后Derived::vf
也是虛擬的(無論是否聲明)並且它覆蓋Base::vf
。
- ISO / IEC 14882:2001(E)§10.3(大膽強調我的)
很簡單,在你的第二個例子中的參數列表Second::f(double)
從不同的First::f(int)
所以Second::f(double)
不 (自動),虛擬和不覆蓋First::f(int)
。
C ++ 11關鍵字override
聲明了一個方法覆蓋繼承的虛方法的意圖,以便編譯器可以告訴您何時不這樣做。 例如,如果你這樣做了:
void f(double a) override {
編譯器會給你這個診斷通知你它實際上沒有覆蓋任何東西,它甚至告訴你為什么它沒有( “在第一個參數類型不匹配('int'與'double')” ):
main.cpp:15:18: error: non-virtual member function marked 'override' hides virtual member function
void f(double a) override { //double instead int here!
^
main.cpp:7:14: note: hidden overloaded virtual function 'First::f' declared here: type mismatch at 1st parameter ('int' vs 'double')
virtual void f(int a) {
^
事實上,派生類不會重新聲明基類的虛函數。 他們重新定義了它們,在C ++方面意味着覆蓋基類的虛函數的定義。
在第二個示例中,派生類聲明了一個新的非虛函數(因為函數說明符virtual不存在),其名稱與基類中虛函數的名稱相同。 新聲明的函數隱藏了基類中虛函數的聲明。
在此代碼段中
Second s;
First *p = &s;
p->f(5);
指針p
的靜態類型是First
。 因此,編譯器查看First類中聲明的虛函數表,並找到指向First類中聲明的函數的指針。 此指針不會被派生類中的虛函數的地址覆蓋,因為派生類沒有覆蓋基類函數。
如果你會寫例如
Second s;
Second *p = &s;
^^^^^^
p->f(5);
然后將調用派生類中聲明的非虛函數。
在第二段代碼中,Second繼承了一個名為f()的虛函數,並有自己的函數f()。
現在,因為所有調用都是從First(或First指向的對象)完成的,所以它的工作原理如下:當你從First對象調用時,很明顯將調用First中的函數。 現在,當你從指向First的第二個對象調用時,因為f()是虛擬的,“編譯器”[請看下面的注釋]在實際的類中搜索它(這是第二個)但是從那里開始是沒有匹配void f(int)的函數然后從First獲取一個函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.