C++编译时多态和运行时多态
C++編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài)
作者:melonstreet
出處:https://www.cnblogs.com/QG-whz/p/5132745.html
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
前言
今日的C++不再是個(gè)單純的“帶類的C”語言,它已經(jīng)發(fā)展成為一個(gè)多種次語言所組成的語言集合,其中泛型編程與基于它的STL是C++發(fā)展中最為出彩的那部分。在面向?qū)ο驝++編程中,多態(tài)是OO三大特性之一,這種多態(tài)稱為運(yùn)行期多態(tài),也稱為動(dòng)態(tài)多態(tài);在泛型編程中,多態(tài)基于template(模板)的具現(xiàn)化與函數(shù)的重載解析,這種多態(tài)在編譯期進(jìn)行,因此稱為編譯期多態(tài)或靜態(tài)多態(tài)。在本文中,我們將了解:
運(yùn)行期多態(tài)
運(yùn)行期多態(tài)的設(shè)計(jì)思想要?dú)w結(jié)到類繼承體系的設(shè)計(jì)上去。對(duì)于有相關(guān)功能的對(duì)象集合,我們總希望能夠抽象出它們共有的功能集合,在基類中將這些功能聲明為虛接口(虛函數(shù)),然后由子類繼承基類去重寫這些虛接口,以實(shí)現(xiàn)子類特有的具體功能。典型地我們會(huì)舉下面這個(gè)例子:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-r8RIXVVw-1642570130701)(C++編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài).assets/poly0.png)]
class Animal { public :virtual void shout() = 0; }; class Dog :public Animal { public:virtual void shout(){ cout << "汪汪!"<<endl; } }; class Cat :public Animal { public:virtual void shout(){ cout << "喵喵~"<<endl; } }; class Bird : public Animal { public:virtual void shout(){ cout << "嘰喳!"<<endl; } };int main() {Animal * anim1 = new Dog;Animal * anim2 = new Cat;Animal * anim3 = new Bird;//藉由指針(或引用)調(diào)用的接口,在運(yùn)行期確定指針(或引用)所指對(duì)象的真正類型,調(diào)用該類型對(duì)應(yīng)的接口anim1->shout();anim2->shout();anim3->shout();//delete 對(duì)象...return 0; }運(yùn)行期多態(tài)的實(shí)現(xiàn)依賴于虛函數(shù)機(jī)制。當(dāng)某個(gè)類聲明了虛函數(shù)時(shí),編譯器將為該類對(duì)象安插一個(gè)虛函數(shù)表指針,并為該類設(shè)置一張唯一的虛函數(shù)表,虛函數(shù)表中存放的是該類虛函數(shù)地址。運(yùn)行期間通過虛函數(shù)表指針與虛函數(shù)表去確定該類虛函數(shù)的真正實(shí)現(xiàn)。
運(yùn)行期多態(tài)的優(yōu)勢(shì)還在于它使處理異質(zhì)對(duì)象集合稱為可能:
//我們有個(gè)動(dòng)物園,里面有一堆動(dòng)物 int main() {vector<Animal*>anims;Animal * anim1 = new Dog;Animal * anim2 = new Cat;Animal * anim3 = new Bird;Animal * anim4 = new Dog;Animal * anim5 = new Cat;Animal * anim6 = new Bird;//處理異質(zhì)類集合anims.push_back(anim1);anims.push_back(anim2);anims.push_back(anim3);anims.push_back(anim4);anims.push_back(anim5);anims.push_back(anim6);for (auto & i : anims){i->shout();}//delete對(duì)象//...return 0; }總結(jié):運(yùn)行期多態(tài)通過虛函數(shù)發(fā)生于運(yùn)行期
編譯期多態(tài)
對(duì)模板參數(shù)而言,多態(tài)是通過模板具現(xiàn)化和函數(shù)重載解析實(shí)現(xiàn)的。以不同的模板參數(shù)具現(xiàn)化導(dǎo)致調(diào)用不同的函數(shù),這就是所謂的編譯期多態(tài)。
相比較于運(yùn)行期多態(tài),實(shí)現(xiàn)編譯期多態(tài)的類之間并不需要成為一個(gè)繼承體系,它們之間可以沒有什么關(guān)系,但約束是它們都有相同的隱式接口。我們將上面的例子改寫為:
在編譯之前,函數(shù)模板中t.shout()調(diào)用的是哪個(gè)接口并不確定。在編譯期間,編譯器推斷出模板參數(shù),因此確定調(diào)用的shout是哪個(gè)具體類型的接口。不同的推斷結(jié)果調(diào)用不同的函數(shù),這就是編譯器多態(tài)。這類似于重載函數(shù)在編譯器進(jìn)行推導(dǎo),以確定哪一個(gè)函數(shù)被調(diào)用。
運(yùn)行期多態(tài)與編譯期多態(tài)優(yōu)缺點(diǎn)分析
運(yùn)行期多態(tài)優(yōu)點(diǎn)
運(yùn)行期多態(tài)缺點(diǎn)
編譯期多態(tài)優(yōu)點(diǎn)
編譯期多態(tài)缺點(diǎn)
關(guān)于顯式接口與隱式接口
所謂的顯式接口是指類繼承層次中定義的接口或是某個(gè)具體類提供的接口,總而言之,我們能夠在源代碼中找到這個(gè)接口.顯式接口以函數(shù)簽名為中心,例如
void AnimalShot(Animal & anim) {anim.shout(); }我們稱shout為一個(gè)顯式接口。在運(yùn)行期多態(tài)中的接口皆為顯式接口。
而對(duì)模板參數(shù)而言,接口是隱式的,奠基于有效表達(dá)式。例如:
template <typename T> void AnimalShot(T & anim) {anim.shout(); }對(duì)于anim來說,必須支持哪一種接口,要由模板參數(shù)執(zhí)行于anim身上的操作來決定,在上面這個(gè)例子中,T必須支持shout()操作,那么shout就是T的一個(gè)隱式接口。
總結(jié)
以上是生活随笔為你收集整理的C++编译时多态和运行时多态的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人寿保险是国企还是私企
- 下一篇: C++中的虚函数(表)实现机制以及用C语