在前几篇博客中介绍了继承,并且通过几个实例描述了继承的的实现方式和在编程中的意义
今天将引入一个新的概念----------------多重继承
多重继承-------------多重继承是指一个子类是由多个父类派生出来的
需要说明的是多重继承在实际编程中并不常用,因为在使用过程中容易出现多重继承的二义性
为了避免出现多重继承的二义性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");
}
执行结果: