寫正題以前,先給出幾個關鍵字的中英文對照,重載(overload),覆蓋(override),隱藏(hide)。在早期的C++書籍中,可能翻譯的人不熟悉專業用語(也不能怪他們,他們不是搞計算機編程的,他們是英語專業的),經常把重載(overload)和覆蓋(override)搞錯!ios
咱們先來看一些代碼及其編譯結果。編程
實例一:
#include "stdafx.h"
#include <iostream.h>ide
class CB
{
public:
void f(int)
{
cout << "CB::f(int)" << endl;
}函數
};測試
class CD : public CB
{
public:
void f(int,int)
{
cout << "CD::f(int,int)" << endl;
}google
void test()
{
f(1);
}
};spa
int main(int argc, char* argv[])
{
return 0;
}
編譯了一下
error C2660: 'f' : function does not take 1 parameters翻譯
結論:在類CD這個域中,沒有f(int)這樣的函數,基類中的void f(int)被隱藏指針
若是把派生CD中成員函數void f(int,int)的聲明改爲和基類中同樣,即f(int),基類中的void f(int)仍是同樣被覆蓋,此時編譯不會出錯,在函數中test調用的是CD中的f(int) orm
因此,在基類中的某些函數,若是沒有virtral關鍵字,函數名是f(參數是什麼咱們無論),那麼若是在派生類CD中也聲明瞭某個f成員函數,那麼在類CD域中,基類中全部的那些f都被隱藏。
若是你比較心急,想知道什麼是隱藏,看文章最後的簡單說明,不過我建議你仍是一步一步看下去。
咱們剛纔說的是沒有virtual的狀況,若是有virtual的狀況呢??
實例二:
#include "stdafx.h"
#include <iostream.h>
class CB
{
public:
virtual void f(int)
{
cout << "CB::f(int)" << endl;
}
};
class CD : public CB
{
public:
void f(int)
{
cout << "CD::f(int)" << endl;
}
};
int main(int argc, char* argv[])
{
return 0;
}
這麼寫固然是沒問題了,在這裏我很少費口舌了,這是很簡單的,多態,虛函數,而後什麼指向基類的指針指向派生類對象阿,經過引用調用虛函數阿什麼的,屬性多的很咯,什麼??你不明白??隨便找本C++的書,對會講多態和虛函數機制的哦!!
這種狀況咱們叫覆蓋(override)!覆蓋指的是派生類的虛擬函數覆蓋了基類的同名且參數相同的函數!
在這裏,我要強調的是,這種覆蓋,要知足兩個條件
(a)有virtual關鍵字,在基類中函數聲明的時候加上就能夠了
(b)基類CB中的函數和派生類CD中的函數要如出一轍,什麼叫如出一轍,函數名,參數,返回類型三個條件。
有人可能會對(b)中的說法質疑,說返回類型也要同樣??
是,覆蓋的話必須同樣,我試了試,若是在基類中,把f的聲明改爲virtual int f(int),編譯出錯了
error C2555: 'CD::f' : overriding virtual function differs from 'CB::f' only by return type or calling convention
因此,覆蓋的話,必需要知足上述的(a)(b)條件
那麼若是基類CB中的函數f有關鍵字virtual ,可是參數和派生類CD中的函數f參數不同呢,
實例三:
#include "stdafx.h"
#include <iostream.h>
class CB
{
public:
virtual void f(int)
{
cout << "CB::f(int)" << endl;
}
}
;
class CD : public CB
{
public:
void f(int,int)
{
cout << "CD::f(int,int)" << endl;
}
void test()
{
f(1);
}
}
;
int main(int argc, char* argv[])
{
return 0;
}
編譯出錯了,
error C2660: 'f' : function does not take 1 parameters
咦??好面熟的錯??對,和實例一中的狀況同樣哦,結論也是基類中的函數被隱藏了。
經過上面三個例子,得出一個簡單的結論
若是基類中的函數和派生類中的兩個名字同樣的函數f
知足下面的兩個條件
(a)在基類中函數聲明的時候有virtual關鍵字
(b)基類CB中的函數和派生類CD中的函數如出一轍,函數名,參數,返回類型都同樣。
那麼這就是叫作覆蓋(override),這也就是虛函數,多態的性質
那麼其餘的狀況呢??只要名字同樣,不知足上面覆蓋的條件,就是隱藏了。
下面我要講最關鍵的地方了,好多人認爲,基類CB中的f(int)會繼承下來和CD中的f(int,int)在派生類CD中構成重載,就像實例一中想像的那樣。
對嗎?咱們先看重載的定義
重載(overload):
必須在一個域中,函數名稱相同可是函數參數不一樣,重載的做用就是同一個函數有不一樣的行爲,所以不是在一個域中的函數是沒法構成重載的,這個是重載的重要特徵
必須在一個域中,而繼承明顯是在兩個類中了哦,因此上面的想法是不成立的,咱們測試的結構也是這樣,派生類中的f(int,int)把基類中的f(int)隱藏了
因此,相同的函數名的函數,在基類和派生類中的關係只能是覆蓋或者隱藏。
在文章中,我把重載和覆蓋的定義都給了出來了,可是一直沒有給隱藏的定義,在最後,我把他給出來,這段話是網上google來的,比較長,你能夠簡單的理解成,在派生類域中,看不到基類中的那個同名函數了,或者說,是並無繼承下來給你用,呵呵,如實例一 那樣。
隱藏(hide):指的是派生類的成員函數隱藏了基類函數的成員函數.隱藏一詞能夠這麼理解:在調用一個類的成員函數的時候,編譯器會沿着類的繼承鏈逐級的向上查找函數的定義,若是找到了那麼就中止查找了,因此若是一個派生類和一個基類都有同一個同名(暫且不論參數是否相同)的函數,而編譯器最終選擇了在派生類中的函數,那麼咱們就說這個派生類的成員函數"隱藏"了基類的成員函數,也就是說它阻止了編譯器繼續向上查找函數的定義