转载:C++编译期多态与运行期多态
前言
今日的C++不再是個單純的“帶類的C”語言,它已經發展成為一個多種次語言所組成的語言集合,其中泛型編程與基于它的STL是C++發展中最為出 彩的那部分。在面向對象C++編程中,多態是OO三大特性之一,這種多態稱為運行期多態,也稱為動態多態;在泛型編程中,多態基于template(模 板)的具現化與函數的重載解析,這種多態在編譯期進行,因此稱為編譯期多態或靜態多態。在本文中,我們將了解:
運行期多態
運行期多態的設計思想要歸結到類繼承體系的設計上去。對于有相關功能的對象集合,我們總希望能夠抽象出它們共有的功能集合,在基類中將這些功能聲明為虛接口(虛函數),然后由子類繼承基類去重寫這些虛接口,以實現子類特有的具體功能。典型地我們會舉下面這個例子:
運行期多態的實現依賴于虛函數機制。當某個類聲明了虛函數時,編譯器將為該類對象安插一個虛函數表指針,并為該類設置一張唯一的虛函數表,虛函數表中存放的是該類虛函數地址。運行期間通過虛函數表指針與虛函數表去確定該類虛函數的真正實現。
運行期多態的優勢還在于它使處理異質對象集合稱為可能:
//我們有個動物園,里面有一堆動物 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; //處理異質類集合 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對象 //... return 0; }總結:運行期多態通過虛函數發生于運行期
回到頂部編譯期多態
對模板參數而言,多態是通過模板具現化和函數重載解析實現的。以不同的模板參數具現化導致調用不同的函數,這就是所謂的編譯期多態。
相比較于運行期多態,實現編譯期多態的類之間并不需要成為一個繼承體系,它們之間可以沒有什么關系,但約束是它們都有相同的隱式接口。我們將上面的例子改寫為:
在編譯之前,函數模板中t.shout()調用的是哪個接口并不確定。在編譯期間,編譯器推斷出模板參數,因此確定調用的shout是哪個具體類型的接口。不同的推斷結果調用不同的函數,這就是編譯器多態。這類似于重載函數在編譯器進行推導,以確定哪一個函數被調用。
回到頂部運行期多態與編譯期多態優缺點分析
運行期多態優點
運行期多態缺點
虛表指針增大了對象體積,類也多了一張虛函數表,當然,這是理所應當值得付出的資源消耗,列為缺點有點勉強。
編譯期多態優點
具有很強的適配性與松耦合性,對于特殊類型可由模板偏特化、全特化來處理。
編譯期多態缺點
關于顯式接口與隱式接口
所謂的顯式接口是指類繼承層次中定義的接口或是某個具體類提供的接口,總而言之,我們能夠在源代碼中找到這個接口.顯式接口以函數簽名為中心,例如
void AnimalShot(Animal & anim) { anim.shout(); }我們稱shout為一個顯式接口。在運行期多態中的接口皆為顯式接口。
而對模板參數而言,接口是隱式的,奠基于有效表達式。例如:
template <typename T> void AnimalShot(T & anim) { anim.shout(); }對于anim來說,必須支持哪一種接口,要由模板參數執行于anim身上的操作來決定,在上面這個例子中,T必須支持shout()操作,那么shout就是T的一個隱式接口。
轉自:http://www.cnblogs.com/QG-whz/p/5132745.html
轉載于:https://www.cnblogs.com/xixi-/p/5453403.html
總結
以上是生活随笔為你收集整理的转载:C++编译期多态与运行期多态的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ4568 : [Scoi2016
- 下一篇: C++版 - 剑指offer面试题38: