一、多態(tài)的概念
在說多態(tài)之前,我們來先看一看對象的類型
來看一個例子:
多態(tài):意思既是同一個事物的多種形態(tài),用我們C++的專業(yè)詞語來說就是:一個借口、多種實現(xiàn)方式。
二、多態(tài)分類
靜態(tài)多態(tài):
靜態(tài)多態(tài):編譯器在編譯期間完成的,編譯器根據(jù)函數(shù)實參的類型(可能會進行隱式類型轉(zhuǎn)換),可推斷出要調(diào)用那個函數(shù),如果有對應的函數(shù)就調(diào)用該函數(shù),否則出現(xiàn)編譯錯誤。
動態(tài)多態(tài):
動態(tài)多態(tài)就是我們常說的多態(tài)。動態(tài)多態(tài)是在程序運行期間才決定調(diào)用哪個函數(shù),是根據(jù)虛函數(shù)表實現(xiàn)的。聲明了虛函數(shù)的類,類中都有一張?zhí)摵瘮?shù)表,里面存放類的入口地址。通過賦值兼容規(guī)則,可以用父類的指針或引用找到子類的虛函數(shù)。虛函數(shù)是處理類的派生體系中不同層次上不同作用域的同名問題,因此動態(tài)多態(tài)必須在類的繼承體系中才能實現(xiàn)。
三、多態(tài)的實現(xiàn)原理(動態(tài))
說到這里,有幾個非常重要的概念,需要我們加以區(qū)分:重載、重寫、重定義
通過上面的多態(tài)的介紹,這里來說幾個重要的概念:
(1)虛函數(shù)表指針:類中除了定義成員函數(shù)之外還有一個成員是虛函數(shù)表指針(占四個基本內(nèi)存單位),這個指針指向一個虛函數(shù)表的起始位置,這個表會與類的定義同時出現(xiàn),這個表會與類的定義同時出現(xiàn),這個表存放著該類的虛函數(shù)指針,調(diào)用的時候可以找到該類虛函數(shù)表指針,通過虛函數(shù)表指針找到虛函數(shù)表,通過虛函數(shù)表的偏移找到函數(shù)的入口地址,從而找到要使用的虛函數(shù)。
(2)當實例化一個該類的子類對象的時候,(如果)該類的子類并沒有定義虛函數(shù),但是卻從父類中繼承了虛函數(shù),所以在實例化該類子類對象的時候也會產(chǎn)生一個虛函數(shù)表,這個虛函數(shù)表是子類的虛函數(shù)表,但是記錄的子類的虛函數(shù)地址卻是與父類的是一樣的。所以通過子類對象的虛函數(shù)表指針找到自己的虛函數(shù)表,在自己的虛函數(shù)表找到的要執(zhí)行的函數(shù)指針也是父類的相應函數(shù)入口的地址。
(3)如果我們在子類中定義了從父類繼承來的虛函數(shù),對于父類來說情況是不變的,對于子類來說它的虛函數(shù)表與之前的虛函數(shù)表是一樣的,但是此時子類定義了自己的(從父類那繼承來的)相應函數(shù),所以它的虛函數(shù)表當中管于這個函數(shù)的指針就會覆蓋掉原有的指向父類函數(shù)的指針的值,換句話說就是指向了自己定義的相應函數(shù),這樣如果用父類的指針,指向子類的對象,就會通過子類對象當中的虛函數(shù)表指針找到子類的虛函數(shù)表,從而通過子類的虛函數(shù)表找到子類的相應虛函數(shù)地址,而此時的地址已經(jīng)是該函數(shù)自己定義的虛函數(shù)入口地址,而不是父類的相應虛函數(shù)入口地址,所以執(zhí)行的將會是子類當中的虛函數(shù)。這就是多態(tài)的原理。
(4)純虛函數(shù)
在成員函數(shù)的參數(shù)列表后面寫上“=0”則該成員函數(shù)為純虛函數(shù)。
包含純虛函數(shù)的類叫做抽象類(也叫接口類),抽象類不能實例化出對象。
純虛函數(shù)在抽象類中重新定義以后,派生類才能實現(xiàn)實例化出對象。
總結(jié):
(1)派生類重寫基類的虛函數(shù)實現(xiàn)多態(tài),要求函數(shù)名、參數(shù)列表、返回值完全相同(協(xié)變除外)
協(xié)變:基類和派生類中的虛函數(shù)名字和參數(shù)列表相同、返回值類型不同,基類中的虛函數(shù)返回Base*,派生類中的虛函數(shù)返回Derived*
(2)基類中定義了虛函數(shù),在派生類中該函數(shù)始終保持虛函數(shù)的特性。
(3)只有類的非靜態(tài)成員函數(shù)才能定義為虛函數(shù),靜態(tài)成員函數(shù)不能定義為虛函數(shù)。
(4)如果在類外定義虛函數(shù),只能在聲明函數(shù)時加virtual關鍵字,定義時不用加。
(5)構造函數(shù)不能定義為虛函數(shù),雖然可以將operator=定義為虛函數(shù),但最好不要這么做,使用時容易混淆
(6)不要在構造函數(shù)和析構函數(shù)中調(diào)用虛函數(shù),在構造函數(shù)和析構函數(shù)中,對象是不完整的,可能會出現(xiàn)未定義的行為。
(7)最好將基類的析構函數(shù)聲明為虛函數(shù)。(析構函數(shù)比較特殊,因為派生類的析構函數(shù)跟基類的析構函數(shù)名稱不一樣,但是構成覆蓋,這里編譯器做了特殊處理)
(8)虛表是對所有類對象實例共用的
-
C++
+關注
關注
22文章
2119瀏覽量
75351 -
動態(tài)多態(tài)
+關注
關注
0文章
4瀏覽量
5982 -
靜態(tài)多態(tài)
+關注
關注
0文章
2瀏覽量
5523
發(fā)布評論請先 登錄
C++的多態(tài)詳解
STM32 C++代碼封裝初探相關資料推薦
C++的動態(tài)多態(tài)和靜態(tài)多態(tài)

java多態(tài)性的實現(xiàn)
C++程序設計教程之多態(tài)的詳細資料說明

C++程序設計教程之多態(tài)性與虛函數(shù)的詳細資料說明

C++基礎語法中的引用、封裝和多態(tài)
在C++中如何用虛函數(shù)實現(xiàn)多態(tài)
STM32 C++編程系列二:STM32 C++代碼封裝初探

如何通過poly實現(xiàn)C++編譯期多態(tài)
虛函數(shù),C++開發(fā)者如何有效利用
深度解析C++中的虛函數(shù)

C++中實現(xiàn)類似instanceof的方法

評論