C++空類編譯器自動生成的6個成員函數

1、問題

       在C++中,編譯器會爲空類提供哪些默認成員函數?分別有什麼樣的功能呢? html

2、詳解

一、空類,聲明時編譯器不會生成任何成員函數

        對於空類,編譯器不會生成任何的成員函數,只會生成1個字節的佔位符。ios

        有時可能會覺得編譯器會爲空類生成默認構造函數等,事實上是不會的,編譯器只會在須要的時候生成6個成員函數:一個缺省的構造函數、一個拷貝構造函數、一個析構函數、一個賦值運算符、一對取址運算符和一個this指針。函數

 代碼:this

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Empty_one  
  5. {  
  6. };  
  7. class Empty_two  
  8. {};  
  9. class Empty_three  
  10. {  
  11.     virtual void fun() = 0;  
  12. };  
  13. class Empty_four :  public Empty_two, public Empty_three  
  14. {  
  15. };  
  16.   
  17. int main()  
  18. {  
  19.   cout<<"sizeof(Empty_one):"<<sizeof(Empty_one)<<endl;  
  20.   cout<<"sizeof(Empty_two):"<<sizeof(Empty_two)<<endl;  
  21.   cout<<"sizeof(Empty_three):"<<sizeof(Empty_three)<<endl;  
  22.   cout<<"sizeof(Empty_four):"<<sizeof(Empty_four)<<endl;  
  23.   return 0;  
  24. }  

運行結果:spa

 

分析:.net

類Empty_one、Empty_two是空類,但空類一樣能夠被實例化,而每一個實例在內存中都有一個獨一無二的地址,爲了達到這個目的,編譯器每每會給一個空類隱含的加一個字節,這樣空類在實例化後在內存獲得了獨一無二的地址,因此sizeof(Empty_one)和sizeof(Empty_two)的大小爲1。指針

類Empty_three裏面因有一個純虛函數,故有一個指向虛函數的指針(vptr),64位系統分配給指針的大小爲8個字節,因此sizeof(Empty_three)的大小爲8。
code

類Empty_four繼承於Empty_two和Empty_three,編譯器取消Empty_two的佔位符,保留一虛函數表,故大小爲8。xml

 

二、空類,定義時會生成6個成員函數

 

        當空類Empty_one定義一個對象時Empty_one pt;sizeof(pt)還是爲1,但編譯器會生成6個成員函數:一個缺省的構造函數、一個拷貝構造函數、一個析構函數、一個賦值運算符、兩個取址運算符。htm

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. class Empty  
  2. {};  

等價於:

 

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. class Empty  
  2. {  
  3.   public:  
  4.     Empty();                            //缺省構造函數  
  5.     Empty(const Empty &rhs);            //拷貝構造函數  
  6.     ~Empty();                           //析構函數   
  7.     Empty& operator=(const Empty &rhs); //賦值運算符  
  8.     Empty* operator&();                 //取址運算符  
  9.     const Empty* operator&() const;     //取址運算符(const版本)  
  10. };  

使用時的調用狀況:

 

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. Empty *e = new Empty();    //缺省構造函數  
  2. delete e;                  //析構函數  
  3. Empty e1;                  //缺省構造函數                                 
  4. Empty e2(e1);              //拷貝構造函數  
  5. e2 = e1;                   //賦值運算符  
  6. Empty *pe1 = &e1;          //取址運算符(非const)  
  7. const Empty *pe2 = &e2;    //取址運算符(const)  

 

C++編譯器對這些函數的實現:

 

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. inline Empty::Empty()                          //缺省構造函數  
  2. {  
  3. }  
  4. inline Empty::~Empty()                         //析構函數  
  5. {  
  6. }  
  7. inline Empty *Empty::operator&()               //取址運算符(非const)  
  8. {  
  9.   return this;   
  10. }             
  11. inline const Empty *Empty::operator&() const    //取址運算符(const)  
  12. {  
  13.   return this;  
  14. }  
  15. inline Empty::Empty(const Empty &rhs)           //拷貝構造函數  
  16. {  
  17.   //對類的非靜態數據成員進行以"成員爲單位"逐一拷貝構造  
  18.   //固定類型的對象拷貝構造是從源對象到目標對象的"逐位"拷貝  
  19. }  
  20.   
  21. inline Empty& Empty::operator=(const Empty &rhs) //賦值運算符  
  22. {  
  23.   //對類的非靜態數據成員進行以"成員爲單位"逐一賦值  
  24.   //固定類型的對象賦值是從源對象到目標對象的"逐位"賦值。  
  25. }  

         例如:m是類C中的一個類型爲T的非靜態成員變量,若C沒有聲明拷貝構造函數(賦值運算符), m將會經過T的拷貝構造函數(賦值運算符)被拷貝構造(賦值);該規則遞歸應用到m的數據成員,直到找到一個拷貝構造函數(賦值運算符)或固定類型(例如:int、double、指針等)爲止。

 

3、總結

(1)上述運行結果依賴於編譯器和64位、32位不一樣的系統。

(2)本博文只是總結一些C++特性,也有沒法理解的地方,不足之處還請指出,在此先感謝!

相關文章
相關標籤/搜索