虛基類的作用


(1):當在多條繼承路徑上有一個公共的基類,在這些路徑的某幾條匯合處,這個公共的基類就會產生多個實例(或多個副本),若只想保存這個基類的一個實例,可以將這個公共基類說明為虛基類、

  class CBase { };

  class ChildA1:virtual public CBase{ };

  class ChildA2:virtual public CBase{ };

  class ChildB:public ChildA1,ChildA2{ };

  則在類ChildB的對象中,僅有類CBase的一個對象數據

 

(2):虛基類的初始化如果在虛基類中定義了帶參數的構造函數,而且沒有定義默認構造函數,則在其所有派生類(包括直接派生或間接派生的派生類)中,通過構造函數的初始化表對虛基類進行初始化。例如
class A//定義基類A
{
   A(int i){ } //基類構造函數,有一個參數

};
class B :virtual public A   //A作為B的虛基類
{
   B(int n):A(n){ } //B類構造函數,在初始化表中對虛基類初始化
};
class C :virtual public A //A作為C的虛基類
{
   C(int n):A(n){ } 
//C類構造函數,在初始化表中對虛基類初始化
};
class D :public B,public C 
//類D的構造函數,在初始化表中對所有基類初始化
{
   D(int n):A(n),B(n),C(n){ }
};
注意: 
在定義類D的構造函數時,與以往使用的方法有所不同。規定: 
在最后的派生類中不僅要負責對其直接基類進行初始化,還要負責對虛基類初始化。C++編譯系統只執行最后的派生類對虛基類的構造函數的調用,而忽略虛基類的其他派生類(如類B和類C) 
對虛基類的構造函數的調用,這就保證了虛基類的數據成員不會被多次初始化。

虛基類的特點:

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

   (2)虛基類的構造函數先於非虛基類的構造函數執行。

 

下面看一段程序的輸出結果:

 1 #include "stdafx.h"
 2 #include<iostream>
 3 using namespace std;
 4 
 5 class CBase{
 6 protected:
 7         int a;
 8 public:
 9     CBase(int na)
10     {
11         a = na;
12         cout << "CBase constructor!" << endl;
13     }
14     ~CBase()
15     {
16         cout << "CBase deconstructor!" << endl;
17     }
18 };
19 
20 class ChildA1: virtual public CBase
21 {
22 public:
23     ChildA1(int na):CBase(na)
24     {
25         cout << "ChildA1 constructor!" << endl;
26     }
27     ~ChildA1()
28     {
29         cout << "ChildA1 deconstructor!" << endl;
30     }
31     int GetA()
32     {
33         return a;
34     }
35 };
36 
37 class ChildA2 : virtual public CBase
38 {
39 public:
40     ChildA2(int na):CBase(na)
41     {
42         cout<< " ChildA2 constructor!" << endl;
43     }
44     ~ChildA2()
45     {
46         cout<< "ChildA2 deconstructor!" << endl;
47     }
48     int GetA()
49     {
50         return a;
51     }
52 };
53 
54 class ChildB:public ChildA1,public ChildA2
55 {
56 public:
57     ChildB(int a1,int a2,int a3):ChildA1(a1),ChildA2(a2),CBase(a3)
58     {
59         cout << "ChildB constructor!!" << endl;
60     }
61     ~ChildB()
62     {
63         cout << "ChildB deconstructor!" << endl;
64     }
65 };
66 
67 int main()
68 {
69     ChildB childb(100,200,300);
70     //得到從ChildA1繼承的值  
71     cout<<" from ChildA1 : a = "<<childb.ChildA1::GetA();  
72     //得到從ChildA2繼承的值  
73     cout<<" from ChildA2 : a = "<<childb.ChildA2::GetA()<<endl<<endl;  
74     return 0;
75 }

程序輸出的結果:

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

  從輸出的結果可以看出來,其公共基類的構造函數只調用了一次,並且優先於非虛基類的構造函數調用,並且發現,子派生類的對象childb的成員變量的值只有一個,所以當公共基類CBase被聲明為虛基類,雖然它成為ChildA1和ChildA2的公共基類,但子派生類ChildB中也只有它的一個備份.


免責聲明!

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



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