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í),為了確保在派生類對(duì)象中能正確定位虛基類的子對(duì)象(包含虛基類的數(shù)據(jù)成員、虛函數(shù)等內(nèi)容),編譯器會(huì)在派生類對(duì)象的內(nèi)存布局中安排虛基類表指針等相關(guān)結(jié)構(gòu)來記錄偏移量信息,以實(shí)現(xiàn)準(zhǔn)確訪問虛基類部分。同時(shí),對(duì)于有虛函數(shù)的類,會(huì)存在虛函數(shù)表(VTable)來支持多態(tài)調(diào)用。
而 vtordisp 主要用于處理虛繼承和虛函數(shù)結(jié)合場景下,構(gòu)造函數(shù)和析構(gòu)函數(shù)中對(duì)虛基類指針調(diào)整的一種機(jī)制,它本質(zhì)上是編譯器為了正確處理對(duì)象的初始化和析構(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)考慮
- 不同的編譯器對(duì)于
vtordisp的處理可能會(huì)有一些差異,有些編譯器可能會(huì)根據(jù)具體的類層次結(jié)構(gòu)復(fù)雜度、是否確實(shí)存在需要調(diào)整虛基類指針偏移量的情況等來決定是否啟用vtordisp機(jī)制以及如何分配相應(yīng)的字節(jié)來存儲(chǔ)相關(guān)信息。比如在 Visual C++ 編譯器中,對(duì)于符合特定條件的虛繼承和虛函數(shù)結(jié)合的場景,會(huì)自動(dòng)插入vtordisp相關(guān)代碼來處理對(duì)象布局和操作順序問題,而在 GCC 等其他編譯器中,也有其對(duì)應(yīng)的實(shí)現(xiàn)方式和判斷標(biāo)準(zhǔn)來確保在類似場景下的代碼正確性。
如果不想要vtordisp 可以加 #pragma vtordisp(off) 進(jìn)行關(guān)閉。
vtordisp是Visual C++編譯器的一個(gè)特性,主要用于解決在類繼承中,虛函數(shù)的調(diào)用與對(duì)象布局的問題。當(dāng)你在類中使用了虛函數(shù),并且該類被繼承,且繼承類覆蓋了基類的虛函數(shù)時(shí),可能會(huì)出現(xiàn)所謂的"跳躍問題"(slicing problem)。
"跳躍問題"是指當(dāng)你有一個(gè)基類的指針指向派生類對(duì)象,并且調(diào)用了虛擬函數(shù),預(yù)期是派生類的函數(shù)被調(diào)用,但實(shí)際上可能會(huì)調(diào)用基類的函數(shù)。這是因?yàn)榫幾g器為了能夠快速地調(diào)用虛擬函數(shù),直接使用了指針的偏移量來計(jì)算虛擬函數(shù)的地址,而不是檢查實(shí)際對(duì)象的類型。
為了解決這個(gè)問題,當(dāng)你在類中有一個(gè)或多個(gè)虛擬函數(shù),并且類被繼承,且派生類覆蓋了基類的虛函數(shù)時(shí),編譯器可能會(huì)為類添加一個(gè)額外的隱藏成員,稱為vtordisp字段。vtordisp字段的作用是在構(gòu)造函數(shù)和析構(gòu)函數(shù)執(zhí)行過程中,記錄對(duì)象的實(shí)際類型信息,以便正確地調(diào)用虛擬函數(shù)。具體由編譯器進(jìn)行管理。
在網(wǎng)上搜集資料并未搞清楚其底層原理,請(qǐng)知道的大佬不吝賜教。
到此這篇關(guān)于C++ vtordisp的應(yīng)用場景的文章就介紹到這了,更多相關(guān)C++ vtordisp應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言實(shí)現(xiàn)解析csv格式文件的示例代碼
CSV,有時(shí)也稱為字符分隔值,其文件以純文本形式存儲(chǔ)表格數(shù)據(jù)(數(shù)字和文本),本文為大家整理了C語言解析csv文件的方法,需要的可以參考一下2023-06-06
C/C++ Windows SAPI實(shí)現(xiàn)文字轉(zhuǎn)語音功能
本文通過封裝Windows SAPI(Speech Application Programming Interface),提供了一個(gè)現(xiàn)代化的C++接口實(shí)現(xiàn)文字轉(zhuǎn)語音功能,這篇文章重點(diǎn)給大家介紹C/C++ Windows SAPI自實(shí)現(xiàn)文字轉(zhuǎn)語音功能,感興趣的朋友一起看看吧2025-02-02
C語言實(shí)現(xiàn)括號(hào)配對(duì)的方法示例
本文主要介紹了C語言實(shí)現(xiàn)括號(hào)配對(duì)的方法示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
LintCode-排序列表轉(zhuǎn)換為二分查找樹分析及實(shí)例
這篇文章主要介紹了LintCode-排序列表轉(zhuǎn)換為二分查找樹分析及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04

