虛函數(shù)作為C++的重要特性,讓人又愛(ài)又怕,愛(ài)它功能強(qiáng)大,但又怕駕馭不好,讓它反咬一口,今天我們用CPU的角度,撕掉語(yǔ)法的偽裝,重新認(rèn)識(shí)一下虛函數(shù)。
虛函數(shù)是C++實(shí)現(xiàn)面向?qū)ο笤O(shè)計(jì)及多態(tài)特性的重要手段。沒(méi)有虛函數(shù),C++和C的區(qū)別就不大,都需要借助大量的“函數(shù)指針”,進(jìn)行面向?qū)ο蟮某绦蛟O(shè)計(jì)(特別是功能擴(kuò)展方面)。
有了虛函數(shù)的存在,函數(shù)指針的使用率大大降低,代碼可讀性,代碼數(shù)量都能得到大幅度的改善。
最厲害的是,C++的虛函數(shù)實(shí)現(xiàn)機(jī)制,幾乎同時(shí)在空間、效率上獲得了最優(yōu)解。
學(xué)習(xí)C++,虛函數(shù)是一條必經(jīng)之路!
先來(lái)看兩段簡(jiǎn)單代碼
讓我們先比較一下普通函數(shù)體與虛函數(shù)體有什么區(qū)別,顯然,兩個(gè)函數(shù)是完全一致的,虛函數(shù)跟普通函數(shù)一樣,都會(huì)夾帶一個(gè)隱藏參數(shù)this指針。所以,如你所見(jiàn),虛函數(shù)在實(shí)現(xiàn)方面,跟普通函數(shù)沒(méi)有任何區(qū)別。
讓我們?cè)倏纯凑{(diào)用它們的時(shí)候,會(huì)有什么不同
通過(guò)對(duì)比,大部分地方也是相同的,箭頭指的那兩條指令都是在輸入:隱藏參數(shù) this指針。唯一的區(qū)別是,調(diào)用普通函數(shù)時(shí),call指令的目標(biāo)地址在編譯階段就確定了,也就是所謂的“靜態(tài)綁定”;但調(diào)用虛函數(shù)時(shí),call指令只能根據(jù)rdx寄存器的值來(lái)確定函數(shù)的位置,也就是所謂的“動(dòng)態(tài)綁定”。
再深入理解下這幾條指令
原來(lái)當(dāng)類(lèi)A有虛函數(shù)的時(shí)候,類(lèi)A就會(huì)偷偷生成一個(gè)隱藏成員變量,方便起見(jiàn),我們給這個(gè)隱藏變量起一個(gè)名字:V(指針類(lèi)型),V存放著虛函數(shù)表的地址,根據(jù)偏移,就可以得到要執(zhí)行的vtest_1 的地址,將其存在寄存器rdx里面,隨后一條:call rdx 指令,一個(gè)虛函數(shù)的調(diào)用就完成了。如果說(shuō),類(lèi)的成員函數(shù)會(huì)夾帶隱藏參數(shù) this指針,還能接受的話,那么,我說(shuō)類(lèi)還會(huì)夾帶隱藏變量V,你能接受嗎?如果真的存在隱藏變量V,在哪里給V初始化呢?答案是在A的構(gòu)造函數(shù)中,把V初始化成類(lèi)A的虛函數(shù)表地址,如下:
盡管我沒(méi)有寫(xiě)構(gòu)造函數(shù),編譯器還是會(huì)給我 生成一個(gè)默認(rèn)的構(gòu)造函數(shù) ,它一定、必須要幫我完成隱藏變量V的初始化。
當(dāng)然,A有派生類(lèi)B的話
那么隱藏變量V會(huì)在B的構(gòu)造函數(shù)中被初始化為B的虛函數(shù)表地址,從而保證A、B的虛函數(shù)相互獨(dú)立,井水不犯河水,但考慮到派生類(lèi)B的構(gòu)造函數(shù),還會(huì)調(diào)用基類(lèi)A的構(gòu)造函數(shù)。因此,變量V一會(huì)兒會(huì)被初始化成類(lèi)A的虛函數(shù)表,一會(huì)又會(huì)被初始化成類(lèi)B的虛函數(shù)表,為了避免暈頭,往往會(huì)禁止在構(gòu)造函數(shù)里面調(diào)用虛函數(shù)。
小結(jié)一下:
1、虛函數(shù)在函數(shù)體的實(shí)現(xiàn)方面跟普通函數(shù)沒(méi)有任何區(qū)別。
2、虛函數(shù)的調(diào)用需要借助類(lèi)對(duì)象的隱藏變量 V(vptr)來(lái)完成,隱藏變量V(vptr)會(huì)在構(gòu)造函數(shù)中被初始化成虛函數(shù)表的內(nèi)存地址。
3、調(diào)用任何虛函數(shù)的套路都是一樣的,唯一的區(qū)別是要根據(jù)它們?cè)谔摵瘮?shù)表的位置設(shè)置正確的偏移量。
大家可以看看調(diào)用vtest_1()和調(diào)用vtest_2()的唯一區(qū)別是什么?
不得不佩服虛函數(shù)的實(shí)現(xiàn)方法,幾乎同時(shí)在效率的空間上得到了最優(yōu)解,因?yàn)樘摵瘮?shù)的出現(xiàn),函數(shù)指針的使用率大大降低,如果你還是被函數(shù)指針困擾的時(shí)候,或許可以考慮一下虛函數(shù)。
-
cpu
+關(guān)注
關(guān)注
68文章
10854瀏覽量
211583 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73621 -
虛函數(shù)
+關(guān)注
關(guān)注
0文章
8瀏覽量
1696
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論