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