最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++虛繼承的實現(xiàn)原理由內(nèi)存布局開始講起

 更新時間:2022年06月06日 08:59:59   作者:Fred^_^  
為了解決多繼承時的命名沖突和冗余數(shù)據(jù)問題,C++提出了虛繼承,使得在派生類中只保留一份間接基類的成員,下面我們從內(nèi)存布局看看虛繼承的實現(xiàn)原理

準(zhǔn)備工作

1、VS2012使用命令行選項查看對象的內(nèi)存布局

微軟的Visual Studio提供給用戶顯示C++對象在內(nèi)存中的布局的選項:/d1reportSingleClassLayout。使用方法很簡單,直接在[工具(T)]選項下找到“Visual Studio命令提示(C)”后點擊即可。切換到cpp文件所在目錄下輸入如下的命令即可

c1 [filename].cpp /d1reportSingleClassLayout[className]

其中[filename].cpp就是我們想要查看的class所在的cpp文件,[className]指我們想要查看的class的類名。(下面舉例說明...)

2、查看普通多繼承子類的內(nèi)存布局

既然我們今天講的是虛基類和虛繼承,我們就先用上面介紹的命令提示工具查看一下普通多繼承子類的內(nèi)存布局,可以跟后文虛繼承子類的內(nèi)存布局情況加以比較。

我們新建一個名叫NormalInheritance的cpp文件,輸入一下內(nèi)容。

/**
	普通繼承(沒有使用虛基類)
*/
// 基類A
class A
{
public:
	int dataA;
};
class B : public A
{
public:
	int dataB;
};
class C : public A
{
public:
	int dataC;
};
class D : public B, public C
{
public:
	int dataD;
};

上面是一個簡單的多繼承例子,我們啟動Visual Studio命令提示功能,切換到NormalInheritance.cpp文件所在目錄,輸入一下命令:

c1 NormalInheritance.cpp /d1reportSingleClassLayoutD

我們可以看到class D的內(nèi)存布局如下:

從類D的內(nèi)存布局可以看到A派生出B和C,B和C中分別包含A的成員。再由B和C派生出D,此時D包含了B和C的成員。這樣D中就總共出現(xiàn)了2個A成員。大家注意到左邊的幾個數(shù)字,這幾個數(shù)字表明了D中各成員在D中排列的起始地址,D中的五個成員變量(B::dataA、dataB、C::dataA、dataC、dataD)各占用4個字節(jié),sizeof(D) = 20。

為了跟后文加以比較,我們再來看看B和C的內(nèi)存布局:

虛繼承的內(nèi)存分布情況

上面我們看到了普通多繼承子類的內(nèi)存分布情況,下面我們進入主題,來看看典型的菱形虛繼承子類的內(nèi)存分布情況。

我們新建一個名叫VirtualInheritance的cpp文件,輸入一下內(nèi)容:

/**
	虛繼承(虛基類)
*/
#include <iostream>
// 基類A
class A
{
public:
	int dataA;
};
class B : virtual public A
{
public:
	int dataB;
};
class C : virtual public A
{
public:
	int dataC;
};
class D : public B, public C
{
public:
	int dataD;
};

VirtualInheritance.cpp和NormalInheritance.cpp的不同點在與C和C繼承A時使用了virtual關(guān)鍵字,也就是虛繼承。同樣,我們看看B、C、D類的內(nèi)存布局情況:

我們可以看到,菱形繼承體系中的子類在內(nèi)存布局上和普通多繼承體系中的子類類有很大的不一樣。對于類B和C,sizeof的值變成了12,除了包含類A的成員變量dataA外還多了一個指針vbptr,類D除了繼承B、C各自的成員變量dataB、dataA和自己的成員變量外,還有兩個分別屬于B、C的指針。

那么類D對象的內(nèi)存布局就變成如下的樣子:

  • vbptr:繼承自父類B中的指針
  • int dataB:繼承自父類B的成員變量
  • vbptr:繼承自父類C的指針
  • int dataC:繼承自父類C的成員變量
  • int dataD:D自己的成員變量
  • int A:繼承自父類A的成員變量

顯然,虛繼承之所以能夠?qū)崿F(xiàn)在多重派生子類中只保存一份共有基類的拷貝,關(guān)鍵在于vbptr指針。那vbptr到底指的是什么?又是如何實現(xiàn)虛繼承的呢?其實上面的類D內(nèi)存布局圖中已經(jīng)給出答案:

實際上,vbptr指的是虛基類表指針(virtual base table pointer),該指針指向了一個虛表(virtual table),虛表中記錄了vbptr與本類的偏移地址;第二項是vbptr到共有基類元素之間的偏移量。在這個例子中,類B中的vbptr指向了虛表D::$vbtable@B@,虛表表明公共基類A的成員變量dataA距離類B開始處的位移為20,這樣就找到了成員變量dataA,而虛繼承也不用像普通多繼承那樣維持著公共基類的兩份同樣的拷貝,節(jié)省了存儲空間。

為了進一步確定上面的想法是否正確,我們可以寫一個簡單的程序加以驗證:

int main()
{
	D* d = new D;
	d->dataA = 10;
	d->dataB = 100;
	d->dataC = 1000;
	d->dataD = 10000;
	B* b = d; // 轉(zhuǎn)化為基類B
	C* c = d; // 轉(zhuǎn)化為基類C
	A* fromB = (B*) d;
	A* fromC = (C*) d;
	std::cout << "d address    : " << d << std::endl;
	std::cout << "b address    : " << b << std::endl;
	std::cout << "c address    : " << c << std::endl;
	std::cout << "fromB address: " << fromB << std::endl;
	std::cout << "fromC address: " << fromC << std::endl;
	std::cout << std::endl;
	std::cout << "vbptr address: " << (int*)d << std::endl;
	std::cout << "    [0] => " << *(int*)(*(int*)d) << std::endl;
	std::cout << "    [1] => " << *(((int*)(*(int*)d)) + 1)<< std::endl; // 偏移量20
	std::cout << "dataB value  : " << *((int*)d + 1) << std::endl;
	std::cout << "vbptr address: " << ((int*)d + 2) << std::endl;
	std::cout << "    [0] => " << *(int*)(*((int*)d + 2)) << std::endl;
	std::cout << "    [1] => " << *((int*)(*((int*)d + 2)) + 1) << std::endl; // 偏移量12
	std::cout << "dataC value  : " << *((int*)d + 3) << std::endl;
	std::cout << "dataD value  : " << *((int*)d + 4) << std::endl;
	std::cout << "dataA value  : " << *((int*)d + 5) << std::endl;
}

得到結(jié)果為:

到此這篇關(guān)于C++虛繼承的實現(xiàn)原理由內(nèi)存布局開始講起的文章就介紹到這了,更多相關(guān)C++虛繼承內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實現(xiàn)簡單學(xué)生管理系統(tǒng)

    C語言實現(xiàn)簡單學(xué)生管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡單學(xué)生管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C++實現(xiàn)簡單FTP客戶端軟件開發(fā)

    C++實現(xiàn)簡單FTP客戶端軟件開發(fā)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單FTP客戶端軟件開發(fā),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 關(guān)于C++中數(shù)據(jù)16進制輸出的方法

    關(guān)于C++中數(shù)據(jù)16進制輸出的方法

    本文主要介紹了關(guān)于C++中數(shù)據(jù)16進制輸出的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 基于Qt實現(xiàn)圖片播放器的示例代碼

    基于Qt實現(xiàn)圖片播放器的示例代碼

    這篇文章主要為大家詳細介紹了如何使用qt制作了一個簡單的圖片播放器,可以播放gif、png等格式圖片。文中的示例代碼講解詳細,需要的可以參考一下
    2022-12-12
  • C語言實現(xiàn)個稅計算器

    C語言實現(xiàn)個稅計算器

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)個稅計算器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C++函數(shù)三種傳參形式(指針傳遞、引用傳遞、值傳遞)

    C++函數(shù)三種傳參形式(指針傳遞、引用傳遞、值傳遞)

    不論是哪種參數(shù)傳遞方式,都有形參和實參之分,本文主要介紹了C++函數(shù)三種傳參形式(指針傳遞、引用傳遞、值傳遞),具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 淺析C++函數(shù)模板和類模板

    淺析C++函數(shù)模板和類模板

    C++語言的模板技術(shù)包括函數(shù)模板和類模板,模板技術(shù)是一種代碼重用技術(shù),函數(shù)和類是C++語言中兩種主要的重用代碼形式,這篇文章主要介紹了C++函數(shù)模板和類模板,需要的朋友可以參考下
    2022-07-07
  • C++ 內(nèi)聯(lián)函數(shù)inline案例詳解

    C++ 內(nèi)聯(lián)函數(shù)inline案例詳解

    這篇文章主要介紹了C++ 內(nèi)聯(lián)函數(shù)inline案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • C/C++中如何判斷某一文件或目錄是否存在

    C/C++中如何判斷某一文件或目錄是否存在

    以下文章是對C/C++中判斷某一文件或目錄是否存在的實現(xiàn)代碼進行了詳細的分析介紹,需要的朋友可以參考下
    2013-07-07
  • QT基于TCP實現(xiàn)文件傳輸系統(tǒng)

    QT基于TCP實現(xiàn)文件傳輸系統(tǒng)

    這篇文章主要為大家詳細介紹了QT基于TCP實現(xiàn)文件傳輸系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論

昌黎县| 清河县| 安丘市| 新河县| 南江县| 运城市| 福鼎市| 绍兴县| 绥芬河市| 富锦市| 纳雍县| 华容县| 昂仁县| 银川市| 呈贡县| 射洪县| 漳浦县| 柏乡县| 措美县| 溧水县| 达尔| 新疆| 通州区| 肇源县| 平泉县| 孝感市| 寻甸| 大荔县| 黑河市| 桑日县| 天柱县| 芜湖县| 怀安县| 驻马店市| 临安市| 都匀市| 廊坊市| 南漳县| 镇康县| 奈曼旗| 上蔡县|