在前几篇博客中介绍了继承,并且通过几个实例描述了继承的的实现方式和在编程中的意义
今天将引入一个新的概念----------------多重继承
多重继承-------------多重继承是指一个子类是由多个父类派生出来的
需要说明的是多重继承在实际编程中并不常用,因为在使用过程中容易出现多重继承的二义性
为了避免出现多重继承的二义性C++中引入了虚基类的概念,在Java中不允许使用多重继承
既然C++中有多继承,我们就来看看多继承是什么东东
在前面我提到了多重继承试着一个子类由多个父类派生出来的,我们通过一个图片来描述多重继承
从上面的图中可以看出子类C是由基类A和基类B派生而来,所以子类B继承了基类A和基类B的全部数据成员和成员函数
多重继承中的格式:子类 : 继承方式 父类1, 继承方式 父类 2
程序代码表示如下
#include <iostream> using namespace std; class A//基类A { public: int i; void printI() { cout<<"i = "<<i<<endl; } protected: private: }; class B//基类B { public: int j; void printJ() { cout<<"j = "<<j<<endl; } protected: private: }; //子类C以公有继承的方式继承自基类A和基类B的全部属性 class C : public A, public B { public: protected: private: }; void main() { C c;//定义一个子类C对象 c.i = 9;//子类C调用基类A的数据成员 c.printI();//子类C调用基类A的成员函数 c.j = 10;//子类C调用基类B的数据成员 c.printJ();//子类C调用基类B的成员函数 system("pause"); }
执行结果:
多重继承中的二义性
当基类的数据成员或者成员函数相同时会出现二义性问题
#include <iostream> using namespace std; class A//基类A { public: int i; void print() { cout<<"i = "<<i<<endl; } protected: private: }; class B//基类B { public: int i; void print() { cout<<"i = "<<i<<endl; } protected: private: }; //子类C以公有继承的方式继承自基类A和基类B的全部属性 class C : public A, public B { public: protected: private: }; void main() { C c;//定义一个子类C对象 c.i = 9;//子类C调用基类A的数据成员 c.print();//子类C调用基类A的成员函数 c.i = 10;//子类C调用基类B的数据成员 c.print();//子类C调用基类B的成员函数 system("pause"); }
上面的代码中基类A和基类B的数据成员和成员函数相同,在执行程序时
对于对象c,c调用了数据成语i,和成员函数print(),因为两个基类中都用i和print(),所以对象c不知道调用的是哪个基类的数据成员和成员函数,所以我们把这种调用不明确的问题称为多重继承中的二义性
多重继承中的二义性解决方法1:使用域作用符"::"指明作用域
可以将main()函数中的代码改为
C c;//定义一个子类C对象 c.A::i = 9;//子类C调用基类A的数据成员 c.A::print();//子类C调用基类A的成员函数 c.B::i = 10;//子类C调用基类B的数据成员 c.B::print();//子类C调用基类B的成员函数
程序的全部代码
#include <iostream> using namespace std; class A//基类A { public: int i; void print() { cout<<"i = "<<i<<endl; } protected: private: }; class B//基类B { public: int i; void print() { cout<<"i = "<<i<<endl; } protected: private: }; //子类C以公有继承的方式继承自基类A和基类B的全部属性 class C : public A, public B { public: protected: private: }; void main() { C c;//定义一个子类C对象 c.A::i = 9;//子类C调用基类A的数据成员 c.A::print();//子类C调用基类A的成员函数 c.B::i = 10;//子类C调用基类B的数据成员 c.B::print();//子类C调用基类B的成员函数 system("pause"); }
执行结果
多重继承中二义性的解决方法2:使用虚基类
使用虚基类的的形象图解
解释:
基类A是子类A1的虚基类
基类A是子类A2的虚基类
子类C是虚基类的派生类
虚基类的表示方式:
class 子类 : virtual 继承方式 父类
程序代码
#include <iostream> using namespace std; class A//基类A { public: int i; void print() { cout<<"i = "<<i<<endl; } protected: private: }; class A1 : virtual public A { }; class B1 : virtual public A { }; //子类C以公有继承的方式继承自基类A和基类B的全部属性 class C : public A1, public B1 { public: protected: private: }; void main() { C c;//定义一个子类C对象 c.i = 9;//子类C调用基类A的数据成员 c.print();//子类C调用基类A的成员函数 system("pause"); }
执行结果: