日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解虚函数的实现过程之初探虚表(1)

發布時間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解虚函数的实现过程之初探虚表(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

空對象它有一字節的大小,在沒有任何成員變量但是卻有虛函數的對象里,它的大小是四個字節,這是為什么呢?


因為含有虛函數的對象里,對象的起始地址往后四個字節其實是 一個指針,它指向了一個數組,這個數組的元素是 指針,這些數組的元素指向的地方就是虛函數實現的地方,我們稱這個數組叫做 虛表。而指向這個虛表的指針我們成為 虛表指針。這個對象為什么是4個字節的大小,也就是含有這個虛表指針。

對于開發者而言,虛表指針都是隱藏的,在常規的開發過程中,我們感受不到它們的存在,要想感知它們的存在,看看底層的匯編代碼即可,或者通過c的形式,來實現虛函數的間接調用。

對象中的虛表指針和虛表的關系如下所示:

虛表指針的初始化過程:



40108D~401090把虛表指針放在this指針所指的地方(也就是對象的起始地址),也就是對象開始的前四個字節存放的是虛表指針。

對象的虛表指針初始化是通過編譯器在構造函數內插入代碼來完成的,在用戶沒有編寫構造函數時,由于必須初始化虛表指針,因此編譯器會提供默認的構造函數,以完成虛表指針的初始化。
(這里也就印證了我們之前所發博客 (提供默認構造函數的第一點))

注意:
a.由于虛表信息在編譯后會被鏈接到對應的執行文件中,因此所獲得的虛表地址是一個相對固定的地址。
b.虛表中虛函數的地址的排列順序依據虛函數在類中的聲明順序而定,先聲明的虛函數的地址會被排列在虛表中靠前的位置。即第一個被聲明的虛函數的地址在虛表的首地址處

虛表的元素所指向的函數是如何被進行調用的呢?
解釋:
在虛表指針的初始化過程中,對象執行了構造函數后,就得到了虛表指針,當其它代碼訪問到這個對象的虛函數時,會根據對象的首地址,取出對應虛表元素。當函數被調用時,會間接訪問虛表,得到對應 的虛函數首地址,并調用執行(記住,虛表指針是放在對象里面的,對象,對象,對象

虛表間接尋址尋址訪問的情況只有在使用對象的指針或引用來調用虛函數的時候才會出現;如果直接使用對象來調用自身的虛函數時,沒必要查表訪問,因為已經明確調用的是自身成員函數,根本沒有構成多態問題。

接下來我們看看如何調用自身類中的虛函數的:


它直接通過對象去調用了自身的成員函數,因此編譯器使用了直接調用函數的方式,并未去訪問虛表指針,并沒有間接獲取虛表指針。

仔細分析虛表指針后發現,編譯器隱藏了虛表指針的初始化實現代碼,當類中出現虛函數時,必須在構造函數中對虛表指針執行初始化操作,而沒有虛函數的類對象在構造時,不會進行初始化虛表指針的操作。因此,在分析構造函數時,又增加了一個特性:虛表指針初始化。
如果排除開發者偽造編譯器生成的代碼來誤導分析人員的可能,我們就可以給出一個結論:對于單線繼承的類結構,在其某個成員函數中,將this的地址初始化虛表首指針時,那么我們可以斷定,這個成員函數就是構造函數。

下面來分析一下含有虛表的對象析構函數



兩者對虛表操作幾乎相同,都是將虛表指針設置成當前對象所屬類中的虛表首地址。兩者看似相同,其實差別很大。
構造函數中完成的是初始化虛表指針的工作,執行前**虛表指針并沒有指向虛表地址,**而執行析構函數時,其對象的虛表指針已經指向了某個虛表指針。

大家是否覺得這里是不是很沒有必要呢?這里實際上是還原虛表指針,讓其指向自身的虛表首地址,防止在析構函數中調用虛函數時取到非自身的虛表,從而導致函數調用錯誤
這里也就是前面博客所提到的,在構造函數和析構函數里面會進行虛表覆蓋。不會產生多態。)

總結:
如何識別虛函數:
a.類中隱式定義了一個數據成員
b.該數據成員在首地址處,占4字節
c.構造函數會將此數據成員初始化為某個數組的首地址
d.這個地址屬于數據區,是一個相對固定的地址
e.在這個數組內,每個數組成員都是函數指針
f.仔細觀察這些函數,它們被調用時,第一個參數必然是this指針(要注意調用約定)
g.在這些函數內部,很有可能會對this指針使用相對間接的訪問方式

虛函數系列:
詳解虛函數的實現過程之初探虛表(1)
詳解虛函數的實現過程之單繼承(2)
詳解虛函數的實現過程之多重繼承(3)
詳解虛函數的實現過程之虛基類(4)
詳解虛函數的實現過程之菱形繼承(5)

總結

以上是生活随笔為你收集整理的详解虚函数的实现过程之初探虚表(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。