C++一個類對象的大小計算


  計算一個類對象的大小時的規律:   

 1、空類、單一繼承的空類、多重繼承的空類所占空間大小為:1(字節,下同);

    2、一個類中,虛函數本身、成員函數(包括靜態與非靜態)和靜態數據成員都是不占用類對象的存儲空間的;

    3、因此一個對象的大小≥所有非靜態成員大小的總和(包括動態分配的變量...);

    4、當類中聲明了虛函數(不管是1個還是多個),那么在實例化對象時,編譯器會自動在對象里安插一個指針vPtr指向虛函數表VTable;

    5、虛繼承的情況:虛繼承的實現是通過一個虛基類指針列表;由於涉及到虛函數表和虛基表,會同時增加一個(多重虛繼承下對應多個)vfPtr指針指向虛函數表vfTable和一個vbPtr指針指向虛基表vbTable,這兩者所占的空間大 小為:8(或8乘以多繼承時父類的個數);

    6、在考慮以上內容所占空間的大小時,還要注意編譯器下的“補齊”padding的影響,即編譯器會插入多余的字節補齊;

    7、類對象的大小=各非靜態數據成員(包括父類的非靜態數據成員但都不包括所有的成員函數)的總和+ vfptr指針(多繼承下可能不止一個)+vbptr指針(多繼承下可能不止一個)+編譯器額外增加的字節。

非虛單繼承實例如下:

class A

{

    char k[3];

public:

    virtual void aa()

    {

 

    };

};

class B:public  A

{

    char j[3];

public:

    virtual void bb()

    {

       

    };

};

class C:public  B

{

    char i[3];

public:

    virtual void cc()

    {

       

    };

};

//一個字節   按4字節對齊

 4(指向虛函數的虛指針)+4(自己的數據成員) = 8 

 4(指向虛函數的虛指針)+4(自己的數據成員)+4(父類A的數據成員)=12   

4(指向虛函數的虛指針)+4(自己的數據成員)+8(父類的數據成員)=16

非虛多繼承實例如下:

 

 

 

 

 

 

重寫函數f()

Base -->char 類型

Base1:4(指向虛函數的虛指針)+4(自己的數據成員) = 8

Base2:4(指向虛函數的虛指針)+4(自己的數據成員) = 8

Base3:4(指向虛函數的虛指針)+4(自己的數據成員) = 8

Derive: 4(Base1指向虛函數表的虛指針)+4(Base1繼承的成員變量)+4(Base2指向虛函數表的虛指針)+4(Base2繼承的成員變量)+3(Base1指向虛函數表的虛指針)+4(Base3繼承的成員變量)+4(自己的數據成員)=28

1)虛函數表在最前面的位置。

2)成員變量根據其繼承和聲明順序依次放在后面。

3)每個父類都有自己的虛表。

4)子類的成員函數被放到了第一個父類的表中。

5)內存布局中,其父類布局依次按聲明順序排列。

6)每個父類的虛表中的f()函數都被overwrite成了子類的f()。這樣做就是為了解決不同的父類類型的指針指向同一個子類實例,而能夠調用到實際的函數。

 

非虛繼承的鑽石繼承:

 

 

 

 

   紅色的部分就是重復的部分,就會造成二義性

 

虛繼承的鑽石繼承:

 

 

 

 

 

     可以看出,少了重合的部分。但是,代價是增加了一個虛基類指針vbptr。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM