C++ vtordisp的應(yīng)用場景分析
問題代碼
#include <iostream> using namespace std; class base { public: base() {} virtual void show() { cout << "base:: show"<<endl; } private: int ma; }; class derive:virtual public base { public: derive() {} virtual void show() { cout << "derive:: show"; } private: int mb; }; int main() { cout << sizeof(derive) << endl; }
以上代碼類大小常規(guī)來說應(yīng)該是如下,占16個(gè)字節(jié)大小,但是為何是20呢
預(yù)期結(jié)構(gòu)
class derive size(16): +--- 0 | {vbptr} 4 | mb +--- +--- (virtual base base) 8 | {vfptr} 12 | ma +---
實(shí)際結(jié)構(gòu),占大小20個(gè)字節(jié)
class derive size(20): +--- 0 | {vbptr} 4 | mb +--- 8 | (vtordisp for vbase base) +--- (virtual base base) 12 | {vfptr} 16 | ma +--- derive::$vbtable@: 0 | 0 1 | 12 (derived(derive+0)base) derive::$vftable@: | -12 0 | &(vtordisp) derive::show derive::show this adjustor: 12 vbi: class offset o.vbptr o.vbte fVtorDisp base 12 0 4 1
經(jīng)過驗(yàn)證 必須滿足以下兩個(gè)條件
- 派生類重寫了虛基類的虛函數(shù)。
- 派生類定義了構(gòu)造函數(shù)或者析構(gòu)函數(shù)。
才會(huì)產(chǎn)生vtordisp.
這就牽扯到vtordisp了,介紹如下
1. 基本概念回顧
在 C++ 中,當(dāng)涉及虛繼承時(shí),為了確保在派生類對象中能正確定位虛基類的子對象(包含虛基類的數(shù)據(jù)成員、虛函數(shù)等內(nèi)容),編譯器會(huì)在派生類對象的內(nèi)存布局中安排虛基類表指針等相關(guān)結(jié)構(gòu)來記錄偏移量信息,以實(shí)現(xiàn)準(zhǔn)確訪問虛基類部分。同時(shí),對于有虛函數(shù)的類,會(huì)存在虛函數(shù)表(VTable)來支持多態(tài)調(diào)用。
而 vtordisp
主要用于處理虛繼承和虛函數(shù)結(jié)合場景下,構(gòu)造函數(shù)和析構(gòu)函數(shù)中對虛基類指針調(diào)整的一種機(jī)制,它本質(zhì)上是編譯器為了正確處理對象的初始化和析構(gòu)順序、保證虛基類相關(guān)操作的正確性而引入的一個(gè)額外的字節(jié)(在 32 位系統(tǒng)下通常是 4 字節(jié),64 位系統(tǒng)下通常是 8 字節(jié))來存儲(chǔ)偏移量相關(guān)信息。
2. 應(yīng)用場景
虛繼承與虛函數(shù)并存的類層次結(jié)構(gòu)
- 場景描述:當(dāng)類層次結(jié)構(gòu)中既有虛繼承又有類自身包含虛函數(shù)的情況時(shí),在派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)中,需要準(zhǔn)確地處理與虛基類相關(guān)的初始化和清理工作,同時(shí)還要考慮虛函數(shù)機(jī)制帶來的多態(tài)性影響。
3. 編譯器相關(guān)考慮
- 不同的編譯器對于
vtordisp
的處理可能會(huì)有一些差異,有些編譯器可能會(huì)根據(jù)具體的類層次結(jié)構(gòu)復(fù)雜度、是否確實(shí)存在需要調(diào)整虛基類指針偏移量的情況等來決定是否啟用vtordisp
機(jī)制以及如何分配相應(yīng)的字節(jié)來存儲(chǔ)相關(guān)信息。比如在 Visual C++ 編譯器中,對于符合特定條件的虛繼承和虛函數(shù)結(jié)合的場景,會(huì)自動(dòng)插入vtordisp
相關(guān)代碼來處理對象布局和操作順序問題,而在 GCC 等其他編譯器中,也有其對應(yīng)的實(shí)現(xiàn)方式和判斷標(biāo)準(zhǔn)來確保在類似場景下的代碼正確性。
如果不想要vtordisp 可以加 #pragma vtordisp(off) 進(jìn)行關(guān)閉。
vtordisp是Visual C++編譯器的一個(gè)特性,主要用于解決在類繼承中,虛函數(shù)的調(diào)用與對象布局的問題。當(dāng)你在類中使用了虛函數(shù),并且該類被繼承,且繼承類覆蓋了基類的虛函數(shù)時(shí),可能會(huì)出現(xiàn)所謂的"跳躍問題"(slicing problem)。
"跳躍問題"是指當(dāng)你有一個(gè)基類的指針指向派生類對象,并且調(diào)用了虛擬函數(shù),預(yù)期是派生類的函數(shù)被調(diào)用,但實(shí)際上可能會(huì)調(diào)用基類的函數(shù)。這是因?yàn)榫幾g器為了能夠快速地調(diào)用虛擬函數(shù),直接使用了指針的偏移量來計(jì)算虛擬函數(shù)的地址,而不是檢查實(shí)際對象的類型。
為了解決這個(gè)問題,當(dāng)你在類中有一個(gè)或多個(gè)虛擬函數(shù),并且類被繼承,且派生類覆蓋了基類的虛函數(shù)時(shí),編譯器可能會(huì)為類添加一個(gè)額外的隱藏成員,稱為vtordisp字段。vtordisp字段的作用是在構(gòu)造函數(shù)和析構(gòu)函數(shù)執(zhí)行過程中,記錄對象的實(shí)際類型信息,以便正確地調(diào)用虛擬函數(shù)。具體由編譯器進(jìn)行管理。
在網(wǎng)上搜集資料并未搞清楚其底層原理,請知道的大佬不吝賜教。
到此這篇關(guān)于C++ vtordisp的應(yīng)用場景的文章就介紹到這了,更多相關(guān)C++ vtordisp應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)飛機(jī)訂票系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)飛機(jī)訂票系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C++中的頭文件與Extern(外部函數(shù)調(diào)用)方式
這篇文章主要介紹了C++中的頭文件與Extern(外部函數(shù)調(diào)用)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08c++如何在主函數(shù)文件中調(diào)用其他函數(shù)文件
這篇文章主要介紹了c++如何在主函數(shù)文件中調(diào)用其他函數(shù)文件問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08詳解設(shè)計(jì)模式中的Command命令模式及相關(guān)C++實(shí)現(xiàn)
這篇文章主要介紹了詳解設(shè)計(jì)模式中的Command命令模式及相關(guān)C++實(shí)現(xiàn),命令模式強(qiáng)調(diào)調(diào)用操作的對象和操作的具體實(shí)現(xiàn)者之間的解耦,需要的朋友可以參考下2016-03-03C語言數(shù)據(jù)結(jié)構(gòu)與算法之圖的遍歷(一)
這篇文章主要是介紹了利用深度優(yōu)先算法實(shí)現(xiàn)圖的遍歷,文中利用圖文詳細(xì)的介紹了實(shí)現(xiàn)步驟,對我們學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法有一定的幫助,需要的朋友可以參考一下2021-12-12C語言實(shí)現(xiàn)簡易通訊錄(靜態(tài)版本)的代碼分享
這篇文章主要為大家詳細(xì)介紹了如何錄音C語言實(shí)現(xiàn)一個(gè)簡易的通訊錄(靜態(tài)版本),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-10-10求斐波那契(Fibonacci)數(shù)列通項(xiàng)的七種實(shí)現(xiàn)方法
本篇文章是對求斐波那契(Fibonacci)數(shù)列通項(xiàng)的七種實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C++實(shí)現(xiàn)拓?fù)渑判颍ˋOV網(wǎng)絡(luò))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)拓?fù)渑判?,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04