天天看點

C++虛基類作用

當一個基類被聲明為虛基類後,即使它成為了多繼承鍊路上的公共基類,最後的派生類中也隻有它的一個備份。例如:

class CBase { };

class CDerive1:virtual public CBase{ };

class CDerive2:virtual public CBase{ };

class CDerive12:public CDerive1,CDerive2{ };

則在類CDerive12的對象中,僅有類CBase的一個對象資料

虛基類的特點:

       虛基類構造函數的參數必須由最新派生出來的類負責初始化(即使不是直接繼承);

       虛基類的構造函數先于非虛基類的構造函數執行。

重寫“C++學習筆記(9)——使用範圍運算符解決繼承中的二義性問題 ”中的程式,觀察虛基類的作用

代碼如下:

[cpp]  view plain copy

  1. #include <IOSTREAM.H>  
  2. //基類  
  3. class CBase  
  4. ...{  
  5. protected:  
  6.     int a;  
  7. public:  
  8.     CBase(int na)  
  9.     ...{  
  10.         a=na;  
  11.         cout<<"CBase constructor! ";  
  12.     }  
  13.     ~CBase()...{cout<<"CBase deconstructor! ";}  
  14. };  
  15. //派生類1(聲明CBase為虛基類)  
  16. class CDerive1:virtual public CBase  
  17. ...{  
  18. public:  
  19.     CDerive1(int na):CBase(na)  
  20.     ...{  
  21.         cout<<"CDerive1 constructor! ";  
  22.     }  
  23.     ~CDerive1()...{cout<<"CDerive1 deconstructor! ";}  
  24.     int GetA()...{return a;}  
  25. };  
  26. //派生類2(聲明CBase為虛基類)  
  27. class CDerive2:virtual public CBase  
  28. ...{  
  29. public:  
  30.     CDerive2(int na):CBase(na)  
  31.     ...{  
  32.         cout<<"CDerive2 constructor! ";  
  33.     }  
  34.     ~CDerive2()...{cout<<"CDerive2 deconstructor! ";}  
  35.     int GetA()...{return a;}  
  36. };  
  37. //子派生類  
  38. class CDerive12:public CDerive1,public CDerive2  
  39. ...{  
  40. public:  
  41.     CDerive12(int na1,int na2,int na3):CDerive1(na1),CDerive2(na2),CBase(na3)  
  42.     ...{  
  43.         cout<<"CDerive12 constructor! ";  
  44.     }  
  45.     ~CDerive12()...{cout<<"CDerive12 deconstructor! ";}  
  46. };  
  47. void main()  
  48. ...{  
  49.     CDerive12 obj(100,200,300);  
  50.     //得到從CDerive1繼承的值  
  51.     cout<<" from CDerive1 : a = "<<obj.CDerive1::GetA();  
  52.     //得到從CDerive2繼承的值  
  53.     cout<<" from CDerive2 : a = "<<obj.CDerive2::GetA()<<endl<<endl;  
  54. }  

1. 子派生類對象的值:

C++虛基類作用

     從上例可以看出,在類CDerived12的構造函數初始化表中,調用了間接基類CBase的構造函數,這對于非虛基類是非法的,但對于虛基類則是合法且必要的。

  對于派生類CDerived1和CDerived2,不論是其内部實作,還是執行個體化的對象,基類CBase是否是它們的虛基類是沒有影響的。受到影響的是它們的派生類CDerived12,因為它從兩條路徑都能到達CBase。

2. 運作結果:

C++虛基類作用

    由此可知,其公共基類的構造函數隻調用了一次,并且優先于非基類的構造函數調用;并且發現,子派生類的對象obj的成員變量的值隻有一個,是以,當公共基類CBase被聲明為虛基類後,雖然它成為CDerive1和CDerive2的公共基類,但子派生類CDerive12中也隻有它的一個備份。可以仔細比較與例2的運作結果有什麼不同。

繼續閱讀