在人類最初的時候,你們都是用手吃飯的,可是隨着人類的漫長髮展,漸漸的開始出現等級制度,部落,再以後,就是國家。每一個國家的人吃飯的方式都不同,英國人用刀叉吃飯,中國人用筷子吃飯。因此,若是想用程序來表現就是,現有一個基類(父類),
ide
class Human { public: void eating( void ) { cout << "use hand to eat" << endl; } };
接着,在父類的基礎上,誕生了派生類,英國人,中國人,
函數
class Englishman : public Human { public: //覆寫 void eating(void) { cout << "use knife to eat" << endl; } }; class Chinese : public Human { public: void eating(void) { cout << "use chopstick to eat" << endl; } };
子類繼承了父類的函數,並對其進行修改,固然只是修改函數的內容,並無修改函數的返回值類型,函數名,函數參數,這種叫作函數的「覆寫」。那麼,我如今在global space區域實現一個函數,
this
void test_eating(Human& h) { h.eating(); }
接着,我在主函數中,建立三個對象,
spa
Human h; Englishman e; Chinese c;
而後,我去調用這個test_eating()函數,指針
test_eating(h); test_eating(e); test_eating(c);
那麼,輸出結果會是什麼呢?
對象
很明顯,這不是咱們想要的結果,咱們明明建立了Englishman對象,Chinese對象,調用test_eating()函數時,卻沒法輸出本身類內部的函數。爲了解決這一問題,咱們只要在父類中,對
blog
void eating( void )
這個函數,把它變爲虛函數就好了。只要在函數前加上virtual。實現方式以下:繼承
virtual void eating( void )
對於這種作同一件事,處理的方式卻不一樣,這種在C++中被稱做是「多態」。也就是說,採用相同的調用方法,對於不一樣的對象,會調用不一樣的類裏面的函數。get
當咱們把eating函數變爲虛函數的時候,咱們的目的就達成了。
it
那麼多態採用的是什麼樣的一種機制呢?對於通常的函數,也就是非虛函數,採用的是靜態聯編,也就是說,非虛函數,在編譯時就肯定好了要調用哪一個函數。而對於動態聯編,是在運行時才肯定調用的是哪個函數。那麼動態聯編是如何作到的呢?當一個類內有虛函數時,基於這個類所建立的對象內部都會有一個指針,這個指針指向了虛函數表,當咱們調用函數時,就會根據這個指針找到虛函數表,從而調用虛函數。
那麼多態的使用有沒有什麼特色呢?1.若是調用函數時,傳的是值,那麼就沒有多態,只有傳的是指針或引用纔會有多態。傳值時只能是靜態聯編。2.只有類的成員函數才能聲明爲虛函數。3,靜態成員函數不能是虛函數。4.內聯函數不能是虛函數。5.構造函數不能是虛函數。6.析構函數通常都聲明爲虛函數。7.重載函數不可設置爲虛函數。
有個很關鍵的一點就是,若是要把函數設置爲虛函數,那麼,就得保證函數名相同,函數參數列表相同,函數返回值也應該相同。代碼以下:
class Person { public: virtual void test( void ) { cout << "Human test() " << endl; } } class Englishman { public: virtual void test( void ){ cout << "Englishman test()" << endl; } } class Chinese { public: virtual void test( void ){ cout << "Chinese test()" << endl; } }
這個時候,設置爲虛函數徹底是能夠的。固然也有例外。就是,能夠函數返回值不一樣。函數的返回值類型跟它的類的類型徹底相同,是它的類的指針或引用。代碼以下:
class Person { public: virtual Person* test( void ) { cout << "Human test() " << endl; return this; } } class Englishman { public: virtual English* test( void ){ cout << "Englishman test()" << endl; return this; } } class Chinese { public: virtual Chinese test( void ){ cout << "Chinese test()" << endl; return this; } }
這樣作是徹底能夠的。