原文地址:http://www.diybl.com/course/3_program/c++/cppsl/200899/141320.html
先看如下的图示:
在图中深红色标记出来的地方正是主要问题所在,水陆两用汽车类继承了来自Car类与Boat类的属性与方法,Car类与Boat类同为AmphibianCar类的基类,在内存分配上AmphibianCar获得了来自两个类的SetWeight()成员函数,当我们调用a.SetWeight(3)的时候计算机不知道如何选择分别属于两个基类的被重复拥有了的类成员函数SetWeight()。
由于这种模糊问题的存在同样也导致了AmphibianCar a(4,200,1.35f);执行失败,系统会产生Vehicle”不是基或成员的错误。
以上面的代码为例,我们要想让AmphibianCar类既获得一个Vehicle的拷贝,而且又同时共享用Car类与Boat类的数据成员与成员函数就必须通过C++所提供的虚拟继承技术来实现。
我们在Car类和Boat类继承Vehicle类出,在前面加上virtual关键字就可以实现虚拟继承,使用虚拟继承后,当系统碰到多重继承的时候就会自动先加入一个Vehicle的拷贝,当再次请求一个Vehicle的拷贝的时候就会被忽略,保证继承类成员函数的唯一性。
修改后的代码如下,注意观察变化:
01 | //程序作者:管宁 |
02 | //站点:www.cndev-lab.com |
03 | //所有稿件均有版权,如要转载,请务必著名出处和作者 |
04 | |
05 | #include <iostream> |
06 | using namespace std; |
07 | |
08 | class Vehicle |
09 | { |
10 | public : |
11 | Vehicle( int weight = 0) |
12 | { |
13 | Vehicle::weight = weight; |
14 | cout<< "载入Vehicle类构造函数" <<endl; |
15 | } |
16 | void SetWeight( int weight) |
17 | { |
18 | cout<< "重新设置重量" <<endl; |
19 | Vehicle::weight = weight; |
20 | } |
21 | virtual void ShowMe() = 0; |
22 | protected : |
23 | int weight; |
24 | }; |
25 | class Car: virtual public Vehicle //汽车,这里是虚拟继承 |
26 | { |
27 | public : |
28 | Car( int weight=0, int aird=0):Vehicle(weight) |
29 | { |
30 | Car::aird = aird; |
31 | cout<< "载入Car类构造函数" <<endl; |
32 | } |
33 | void ShowMe() |
34 | { |
35 | cout<< "我是汽车!" <<endl; |
36 | } |
37 | protected : |
38 | int aird; |
39 | }; |
40 | |
41 | class Boat: virtual public Vehicle //船,这里是虚拟继承 |
42 | { |
43 | public : |
44 | Boat( int weight=0, float tonnage=0):Vehicle(weight) |
45 | { |
46 | Boat::tonnage = tonnage; |
47 | cout<< "载入Boat类构造函数" <<endl; |
48 | } |
49 | void ShowMe() |
50 | { |
51 | cout<< "我是船!" <<endl; |
52 | } |
53 | protected : |
54 | float tonnage; |
55 | }; |
56 | |
57 | class AmphibianCar: public Car, public Boat //水陆两用汽车,多重继承的体现 |
58 | { |
59 | public : |
60 | AmphibianCar( int weight, int aird, float tonnage) |
61 | :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage) |
62 | //多重继承要注意调用基类构造函数 |
63 | { |
64 | cout<< "载入AmphibianCar类构造函数" <<endl; |
65 | } |
66 | void ShowMe() |
67 | { |
68 | cout<< "我是水陆两用汽车!" <<endl; |
69 | } |
70 | void ShowMembers() |
71 | { |
72 | cout<< "重量:" <<weight<< "顿," << "空气排量:" <<aird<< "CC," << "排水量:" <<tonnage<< "顿" <<endl; |
73 | } |
74 | }; |
75 | int main() |
76 | { |
77 | AmphibianCar a(4,200,1.35f); |
78 | a.ShowMe(); |
79 | a.ShowMembers(); |
80 | a.SetWeight(3); |
81 | a.ShowMembers(); |
82 | system ( "pause" ); |
83 | } |
结果如下图所示:
注意观察类构造函数的构造顺序。
虽然说虚拟继承与虚函数有一定相似的地方,但读者务必要记住,他们之间是绝对没有任何联系的!