程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++類的大小

C++類的大小

編輯:C++入門知識

一個空類class A{};的大小為什麼是1,因為如果不是1,當定義這個類的對象數組時候A objects[5]; objects[0]和objects[1]就在同一個地址處,就無法區分。

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: public A 

public: 
    virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

VS和gcc下執行結果:

A's size is 8
B's size is 8

說明:有虛函數的類有個virtual table(虛函數表),裡面包含了類的所有虛函數,類中有個virtual table pointers,通常成為vptr指向這個virtual table,占用4個字節的大小。成員類B public繼承於A,類B的虛函數表裡實際上有兩個虛函數A::aa()和B::bb(),類B的大小等於char k[3]的大小加上一個指向虛函數表指針vptr的大小,考慮內存對齊為8。

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: public A 

public: 
    //virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

VS和gcc下結果:

A's size is 8
B's size is 8

說明:類B看上去沒有虛函數,但實際上它有,只是沒有重寫,因為public繼承,所以有從A繼承過來的虛函數A::aa(),實際上類A和類B的虛函數表裡的函數都是A::aa()。
[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
    virtual void aa2(){} 
private: 
    char k[3]; 
}; 
 
class B: public A 

public: 
    virtual void bb(){} 
    virtual void bb2(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

vs和gcc下
執行結果:

A's size is 8
B's size is 8

說明:一個類裡若有虛函數,無論有多少個虛函數都只有一個指向虛表的指針,虛表中的每一個表項保存著一個虛函數的入口地址。當調用虛函數時,先找到虛表中它對應的表項,找到入口地址再執行。對於直接繼承,無論類B中有無虛函數,由於它繼承了類A,且類A裡含有虛函數,因此如果類B有虛函數,那麼它和類A的是在同一個屬於類B的虛表裡。注意:類A裡的私有成員在類B裡仍占有內存。

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: virtual public A 

public: 
    //virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

vs和gcc下
執行結果:A's size is 8
                    B's size is 12
說明:類B裡包含,繼承的char k[3],繼承的虛函數,類B的虛函數表裡有A::aa(),因為是虛繼承,還有一個指向父類的指針,該指針為指向虛基類的指針(Pointer to virtual base class)。考慮內存對齊,總大小為12。

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: public virtual A 

public: 
    virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

VS執行結果:A's size is 8
                         B's size is 16

gcc執行結果:A's size is 8
                          B's size is 12

說明:對於虛繼承,類B虛繼承類A時,首先要通過加入一個指針來指向父類A,該指針被稱為虛基類指針。然後包含從父類繼承過來的3個char,再加上一個虛函數指針。考慮內存對齊,在gcc下結果是4+4+4=12。在VS下,結果是16,why?這一題和上一題區別只是在類B中添加了一個虛函數,但是兩個題目中類B都有虛函數表。在VS下調試查看匯編代碼,發現多出來的4字節什麼也沒有。

關於虛函數、多繼承、虛繼承,可以看《More Effective C++》:理解虛擬函數、多繼承、虛基類和RTTI所需的代價

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved