虚基类的特点:
虚基类构造函数的参数必须由最新派生出来的类负责初始化(即使不是直接继承);
虚基类的构造函数先于非虚基类的构造函数执行。
如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。
C++提供虚基类(virtual base class )的方法,使得在继承间接共同基类时只保留一份成员。
为了保证虚基类在派生类中只继承一次,应当在该基类的所有直接派生类中声明为虚基类。否则仍然会出现对基类的多次继承。
1 #include <iostream>
2 using namespace std;
3 //基类
4 class CBase
5 {
6 protected:
7 int a;
8 public:
9 CBase(int na)
10 {
11 a=na;
12 cout<<"CBase constructor! ";
13 }
14
15 ~CBase(){cout<<"CBase deconstructor! "<<endl;}
16 };
17
18 class UCBase
19 {
20 protected:
21 int a;
22 public:
23 UCBase(int na)
24 {
25 a=na;
26 cout<<"UCBase constructor! ";
27 }
28
29 ~UCBase(){cout<<"UCBase deconstructor! "<<endl;}
30 };
31 //派生类1(声明CBase为虚基类)
32 class CDerive1:virtual public CBase
33 {
34 public:
35 CDerive1(int na):CBase(na)
36 {
37 cout<<"CDerive1 constructor! ";
38 }
39
40 ~CDerive1(){cout<<"CDerive1 deconstructor! "<<endl;;}
41
42 int GetA(){return a;}
43 };
44 class UCDerive1: public UCBase
45 {
46 public:
47 UCDerive1(int na):UCBase(na)
48 {
49 cout<<"UCDerive1 constructor! ";
50 }
51
52 ~UCDerive1(){cout<<"UCDerive1 deconstructor! "<<endl;;}
53
54 int GetA(){return a;}
55 };
56
57 //派生类2(声明CBase为虚基类)
58 class CDerive2:virtual public CBase
59 {
60 public:
61 CDerive2(int na):CBase(na)
62 {
63 cout<<"CDerive2 constructor! ";
64 }
65 ~CDerive2(){cout<<"CDerive2 deconstructor! "<<endl;}
66 int GetA(){return a;}
67 };
68 class UCDerive2:public UCBase
69 {
70 public:
71 UCDerive2(int na):UCBase(na)
72 {
73 cout<<"UCDerive2 constructor! ";
74 }
75 ~UCDerive2(){cout<<"UCDerive2 deconstructor! "<<endl;}
76 int GetA(){return a;}
77 };
78
79 //子派生类
80 class CDerive12:public CDerive1,public CDerive2
81 {
82 public:
83 CDerive12(int na1,int na2,int na3):CDerive1(na1),CDerive2(na2),CBase(na3)
84 {
85 cout<<"CDerive12 constructor! ";
86 }
87 ~CDerive12(){cout<<"CDerive12 deconstructor! "<<endl;}
88 };
89
90 class UCDerive12:public UCDerive1,public UCDerive2,public UCBase
91 {
92 public:
93 UCDerive12(int na1,int na2,int na3):UCDerive1(na1),UCDerive2(na2),UCBase(na3)
94 {
95 cout<<"UCDerive12 constructor! ";
96 }
97 ~UCDerive12(){cout<<"UCDerive12 deconstructor! "<<endl;}
98 };
99
100 int main()
101 {
102 CDerive12 obj(100,200,300);
103 //得到从CDerive1继承的值
104 cout<<" from CDerive1 : a------->"<<obj.CDerive1::GetA()<<endl;;
105 //得到从CDerive2继承的值
106 cout<<" from CDerive2 : a-------> "<<obj.CDerive2::GetA()<<endl<<endl;
107 cout<<"------------------------------------------------------------------"<<endl;
108 UCDerive12 uobj(100,200,300);
109 //得到从CDerive1继承的值
110 cout<<" from UCDerive1 : a------->"<<uobj.UCDerive1::GetA()<<endl;;
111 //得到从CDerive2继承的值
112 cout<<" from UCDerive2 : a-------> "<<uobj.UCDerive2::GetA()<<endl<<endl;
113 return 0;
114 }
温馨提示:使用多重继承时要十分小心,经常会出现二义性问题。许多专业人员认为:不要提倡在 程序中使用多重继承,
只有在比较简单和不易出现二义性的情况或实在必要时才使用多重继承,能用单一继承解决的问题就不要使用多重继承。
也是由于这个原因, 有些面向对象的程序设计语言(如Java,Smalltalk)并不支持多重继承