對象記憶體布局 (13)

來源:互聯網
上載者:User

前篇:http://blog.csdn.net/pathuang68/archive/2009/04/24/4105626.aspx

 

下面來看看虛基類對對象記憶體布局的影響。虛基類的主要作用就是在所有的衍生類別中,保留且僅保留一份虛基類的suboject。

 

a. 一個虛基類的情況

#include <iostream>

using namespace std;

 

class Base

{

public:

         int base_member;

};

 

class Derived : public virtual Base {};

 

int main(void)

{

         Base b;

         Derived d;

 

         cout << sizeof(b) << endl;

         cout << sizeof(d) << endl;

 

         return 0;

}

運行結果:

 

注意使用了虛繼承,即class Derived : public virtual Base。這次Derived的對象大小為什麼為8 bytes呢?這是因為編譯器會給Derived對象安插一個虛基類表指標vbptr,下面給出Derived對象的memory layout:

 

 

虛基類表指標vbptr指向Derived類的virtual bass class table(虛基類表),虛基類表中存放的是Derived類的虛基類表指標到虛基類執行個體指標的位移量。

 

如果Derived有兩個虛基類,那麼這兩個虛基類的執行個體指標,分別位於虛基類表的第2項和第3項,最後一項為0,意味著虛基類表的結束。虛基類表中的第1項是什嗎?目前不清楚,但是它的值大部分時候為0(請牛人指教,編譯器是VC6)。下面我們來檢驗之。

 

在main函數的return前,增加如下語句:

         cout << "Derived object d's vbptr = " << (unsigned long*)(&d) << endl;

         cout << "Address of virtual base class table = " << (unsigned long*)*(unsigned long*)(&d) << endl;

         cout << "Item 1 in virtual base class table = " << *(unsigned long*)*(unsigned long*)(&d) << endl;

         cout << "Item 2 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 1) << endl;

         cout << "Item 3 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 2) << endl;

 

         cout << "The address of virtual base class Base = " << (Base*)(&d) << endl;

編譯後運行結果:

不難發現,虛基類樣本地址 = vbptr + offset,即0x0012FF78 = 0x0012FF74 + 4。圖示如下:

 

b. 我們來看看Derived有兩個虛基類的情況:

#include <iostream>

using namespace std;

class Base1

{

public:

         int base1_member;

};

 

class Base2

{

public:

         int base2_member;

};

 

class Derived : public virtual Base1, public virtual Base2 {};

 

int main(void)

{

         Base1 b1;

         Base2 b2;

         Derived d;

 

         cout << sizeof(b1) << endl;

         cout << sizeof(b2) << endl;

         cout << sizeof(d) << endl;

 

         cout << "Derived object d's vbptr = " << (unsigned long*)(&d) << endl;

         cout << "Address of virtual base class table = " << (unsigned long*)*(unsigned long*)(&d) << endl;

         cout << "Item 1 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 0) << endl;

         cout << "Item 2 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 1) << endl;

         cout << "Item 3 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 2) << endl;

         cout << "Item 3 in virtual base class table = " << *((unsigned long*)*(unsigned long*)(&d) + 3) << endl;

 

         cout << "The address of virtual base class: Base1's instance = " << (Base1*)(&d) << endl;

         cout << "The address of virtual base class: Base2's instance = " << (Base2*)(&d) << endl;

 

         return 0;

}

編譯運行結果如下:

Derived對象的memory layout圖解如下:

 

不管Derived類有多少個虛基類,它只有一個vbptr和一個virtual base class table。

 

後篇:http://blog.csdn.net/pathuang68/archive/2009/04/24/4105851.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.