多態及C++中的多態技術

多態(polymorphism)的字面意思就是多種形態。在程序設計領域,被廣泛認可的一種定義是“將不同的特殊行爲同單個泛化記號相關聯的能力”,簡單來說就是“通過單個標識支持不同行爲的能力”或“單個接口,多種方法”。而在面向對象程序設計中,多態的一般表述是“同一消息(調用函數)發送給不同對象會產生不同的行爲(即有不同的實現)”。例子如讓動物叫,狗會吠叫,雞則會啼叫。

1.維基百科中關於多態的解釋和劃分

在編程語言和類型論中,多態性是使用一個符號表示多個不同類型或者爲不同類型的實體提供一個接口。
維基百科中主要提到了三種多態類型,特設多態(Ad hoc polymorphism)、參數式多態(Parametric polymorphism)和子類型多態(subtype polymorphism)。(https://en.wikipedia.org/wiki/Polymorphism_(computer_science))

  • 特設多態
    特設多態指能夠接受不同類型的參數且依據參數的類型具有不同表現的多態型函數(也即函數重載或運算符重載)。
  • 參數式多態
    參數式多態允許函數或數據類型被泛型地編寫,以便其能統一的處理值而不需要考慮值的類型。C++中的模板就是一種參數式多態。
  • 子類型多態
    子類型多態允許定義一個接受特定類型T對象的函數,但如果傳入一個類型S的對象(類型S是類型T的子類),那麼函數也能正確的工作,並具有不同的行爲。

2.C++中的多態技術

C++中的多態主要分爲兩類:

  1. 動態多態(dynamic polymorphism)
    通過類繼承和虛函數機制生效於運行期,也被稱爲運行時多態或子類型多態(Subtype polymorphism)。其可以優雅地處理異質對象集合,只要異質對象共同的基類定義了虛函數的接口。面向對象程序設計中指的多態就是動態多態。
  2. 靜態多態(static polymorphism)
    通過模板也能實現不同特殊行爲和單個泛化記號相關聯,但這種關聯在編譯期就完成了(通過給模板參數指定類型),因此也被稱作編譯時多態。其可以用來實現類型安全、運行高效的同質對象集合操作。C++ STL採用模板來實現就是個例子。

此外,函數重載機制和帶變量的宏也允許將不同的特殊行爲和單個泛化記號相關聯,可以看成多態現象(分別稱作函數多態和帶變量的宏多態)。然而,習慣上我們並不將它們展現出來的行爲稱爲多態(或靜態多態)。今天,當我們談及多態時,如果沒有明確所指,默認就是動態多態,而靜態多態則是指基於模板的多態(也被稱爲參數式多態)。

詳細解釋和示例代碼參見C++多態技術—靜態多態和動態多態

C++中靜態多態和動態多態的比較(https://www.cnblogs.com/Leo_wl/p/3667870.html):
靜態多態
優點:

  • 由於靜態多態是在編譯期完成的,因此效率較高,編譯器也可以進行優化;
  • 有很強的適配性和松耦合性,比如可以通過偏特化、全特化來處理特殊類型;
  • 最重要一點是靜態多態通過模板編程爲C++帶來了泛型設計的概念,比如強大的STL庫。

缺點:

  • 由於是模板來實現靜態多態,因此模板的不足也就是靜態多態的劣勢,比如調試困難、編譯耗時等
  • 不能夠處理異質對象集合

動態多態
優點:

  • OO設計,是對客觀世界的直覺認識;
  • 實現與接口分離,可複用
  • 處理同一繼承體系下異質對象集合的強大威力

缺點:

  • 運行期綁定,導致一定程度的運行時開銷;
  • 編譯器無法對虛函數進行優化
  • 笨重的類繼承體系,對接口的修改影響整個類層次;

兩者不同點:

  • 本質不同,靜態多態在編譯期決定,由模板具現(實例化)完成,而動態多態在運行期決定,由繼承、虛函數實現;
  • 動態多態中接口是顯式的(在源碼中能找到接口),以函數簽名(函數名、參數、返回值類型)爲中心,多態通過虛函數在運行期實現,靜態多態中接口是隱式的,以有效表達式(模板類型參數聲明)爲中心,多態通過模板具現在編譯期完成

兩者相同點:

  • 都能夠實現多態性,靜態多態/編譯期多態、動態多態/運行期多態;
  • 都能夠使接口和實現相分離,一個是模板定義接口,類型參數定義實現,一個是基類虛函數定義接口,繼承類負責實現;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章