<C++略识>之多重继承、多继承、虚继承
来源:互联网 发布:hg8245超级密码端口23 编辑:程序博客网 时间:2024/04/29 11:44
问题:什么是多重继承?
定义三个类:人、士兵、步兵,则有:步兵->士兵->人,这样的关系称之为多重继承,写法如下:
class Person{};class Soldier:public Person{};class Infrantryman:public Soldier{};
问题:什么是多继承?
定义三个类:农民、工人、农民工,则有:农民工->农民,农民工->工人,这样的关系称之为多继承,写法如下:
class Farmer{};class Worker{};class Migrant:public Farmer, public Worker{};
问题:为什么要有虚继承?是为了解决什么问题?
现象:假如我们有类A是父类,类B和类C继承了类A,而类D既继承类B又继承类C(这种菱形继承关系)。当我们实例化D的对象的时候,每个D的实例化对象中都有了两份完全相同的A的数据。因为保留多份数据成员的拷贝,不仅占用较多的存储空间,还增加了访问这些成员时的困难,容易出错,而实际上,我们并不需要有多份拷贝。
针对这种情况,C++提供虚基类(virtual base class)的方法,使得在继承间接共同基类时只保留一份成员。
现在,将上述类A申明为虚基类,方法如下:
class A //声明基类A{ // 代码};class B: virtual public A //声明类B是类A的公用派生类,A是B的虚基类{ // 代码};class C: virtual public A //声明类C是类A的公用派生类,A是C的虚基类{ // 代码};class D: public B, public C //类D中只有一份A的数据{ // 代码};
[注意]:虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。因为一个基类可以在生成一个派生类时作为虚基类,而在生成另一个派生类时不作为虚基类。
声明虚基类的一般形式为:class 派生类名: virtual 继承方式 基类名
即在声明派生类时,将关键字 virtual 加到相应的继承方式前面,经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承该基类一次,也就是说,基类成员只保留一次。
[注意]:为了保证虚基类在派生类中只继承一次,应当在该基类的所有直接派生类中声明为虚基类,否则仍然会出现对基类的多次继承。比如:在上面的菱形继承关系中,如果在派生类B和C中将类A声明为虚基类,而在派生类D中没有将类A声明为虚基类,则如果再有一个派生类E继承自D,则在E中虽然从类B和C路径派生的部分只保留一份基类成员,但从类D路径派生的部分还保留一份基类成员。
问题:如何对虚基类进行初始化呢?
如果在虚基类中定义了带参数的构造函数,而且没有定义默认构造函数,则在其所有派生类(包括直接派生或间接派生的派生类)中,通过构造函数的初始化列表对虚基类进行初始化。如下:
class A //声明基类A{ A(int i); //申明一个带有参数的构造函数};class B: virtual public A //A是B的虚基类{ B(int n):A(n){ } //B类构造函数,在初始化列表中对虚基类A进行初始化};class C: virtual public A //A是C的虚基类{ C(int n):A(n){ } //C类构造函数,在初始化列表中对虚基类A进行初始化};class D: public B, public C{ D(int n):A(n),B(n),C(n){ } //D类构造函数,在初始化列表中对所有基类进行初始化};
[注意]:在定义类D的构造函数时,与以往使用的方法有所不同。以往,在派生类的构造函数中只需负责对其直接基类初始化,再由其直接基类负责对间接基类初始化。现在,由于虚基类在派生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。如果不由最后的派生类直接对虚基类初始化,而由虚基类的直接派生类(如类B和类C)对虚基类初始化,就有可能由于在类B和类C的构造函数中对虚基类给出不同的初始化参数而产生矛盾。所以规定:在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。
有的读者会提出:类D的构造函数通过初始化表调了虚基类的构造函数A,而类B和类C的构造函数也通过初始化表调用了虚基类的构造函数A,这样虚基类的构造函数岂非被调用了3次?大家不必过虑,C++编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类(如类B和类C) 对虚基类的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化。
- <C++略识>之多重继承、多继承、虚继承
- <C++略识>之多重继承、多继承、虚继承的概念.
- C++之多重继承
- lua 之多重继承
- C++之多重继承
- c++之多重继承
- C++之多重继承
- C++之多重继承
- C++学习之多重继承与虚继承
- C++继承之多重继承与虚基类
- c++基础之多重继承
- 第十二周任务二之多重继承
- 未来的.NET之多重继承
- 多继承 虚继承
- C++之继承(多重继承+多继承+虚继承+虚析构函数+重定义)
- 继承(单继承、多继承、菱形继承、虚继承)
- C#之多继承
- c++之多继承
- jQuery复习
- 基础回顾之:web.xml配置详解
- HTML 超级链接详细讲解
- java中JSON序列化和反序列化工具比较
- 0722 sql 语句那些事
- <C++略识>之多重继承、多继承、虚继承
- Android-Activity生命周期小记
- Build A Binary Search Tree
- 使用gulp+Babel 编译 ES6
- setHeader的参数种类
- CCNA系列十一之Frame-Relay
- 百练2945:拦截导弹(简单dp)
- android培训第12天 7/22
- Android 解决部分手机拍照后获取的图片被旋转的问题