多態實現--虛函數與純虛函數
阿新 • • 發佈:2018-02-04
裏的 對象 ios 動物類 編譯 out 問題 為我 virtual
多態實現--虛函數與純虛函數
- C++中實現多態是使用虛函數表的方法實現的。
- 那麽具體怎麽實現的呢?
舉例說明
- 假設有這樣一個多態場景:
- 有一個基類動物(animal類),動物裏面又有兩個派生類:貓(cat類)和狗(dog類)。現在要求動物類有一個共同的方法:叫聲(voice成員函數),但貓和狗叫聲是不同的(即:它們的叫聲實現方法不同)。
- 那麽代碼怎麽寫呢?
多態的代碼實現
#include <iostream> using namespace std; //1、 定義一個純虛函數 class animal { public: virtual void voice()= 0; //純虛函數voice }; //2、 定義貓(cat)狗(dog)類,共同繼承自animal,但對voice進行了具體實現 class cat:public animal { public: virtual void voice() { cout <<"喵喵喵"<<endl; } }; class dog:public animal { public: virtual void voice() { cout <<"汪汪汪"<<endl; } }; //3、那麽下一步就要給貓和狗做一個統一接口了,傳參用基類指針。這個接口只有一個功能,就是調用動物叫聲voice。 void animal_voice(animal * a) { a->voice(); } //4、 多態寫好了,我們來調用一下試試,寫個test看看這個多態有沒有問題。我們分別定義一個貓狗對象,來調用統一接口,看看它們的叫聲是否相同。 void test() { cat c; dog d; animal_voice(&c); animal_voice(&d); } int main() { test(); return 0; }
驗證結果:
喵喵喵 汪汪汪
說明這個多態已實現完成。
多態原理
那麽多態的原理是怎麽樣的呢?為什麽這樣寫代碼,就能實現貓和狗叫聲不同,它們明明調用的是同一個接口呀?
我們知道C++在編譯時為我們做了很多背後的工作。它為cat和dog分別生成了一張虛函數表,將函數地址(也就是函數指針)記錄在各自的虛函數表中。如圖所示。
- cat的虛函數表:
cat的虛函數表 |
---|
cat的voice函數的地址 |
- dog的虛函數表:
dog的虛函數表 |
---|
dog的voice函數的地址 |
- 這樣當我們用接口調用cat和dog的voice函數時,它們會各自在自己的虛函數表裏找到自己的voice函數地址,然後根據這個地址來進行調用了。怎麽樣,多態實現很簡單吧?
虛函數與純虛函數
- 那麽animal裏的純虛函數virtual void voice()= 0;只能這樣寫嗎?它可以像下面這樣寫成虛函數嗎?
```
virtual void voice()
{
}
```
答案是可以,但它們是不同的。這裏的虛函數是有實現的,只是它的實現方法是空,那麽在cat和dog中我們再次實現這個voice就相當於重寫(也就是說,我們也可以選擇省略(即:不重寫)這個voice)。但如果寫成純虛函數,那麽我們就必須要在cat和dog中具體實現voice。
也就是這裏的虛函數是有這個函數的實現,只是為空;而純虛函數是這個函數根本還沒實現。
多態實現--虛函數與純虛函數