在上篇文章中,给出了关于继承这部分的相关知识,例如继承的定义,继承与默认成员函数等。本文将针对复杂的继承方式,
1. 复杂的继承方式:
1.1 单继承:
class Professor
{
public:int _age;string _name;
};class Teacher : public Professor
{public:int _tele;
};class Student : public Teacher
{
public:int _weight;
};
对于上面给出的代码,如果适用图形来表示这三个类之间的结构,具体如下:
对于这种一个子类只有一个直接父类时,称这种继承关系为单继承。
1.2 多继承:
class Professor
{
public:int _age;string _name;
};class Teacher
{public:int _tele;
};class Student : public Professor, public Teacher
{
public:int _weight;
};
对于上面给出代码,可以用下面的图形来表示这几个类的继承关系:
对于这种一个子类有两个或者两个以上的直接父类的关系,叫做多继承。
在多继承中,存在着一种特殊的继承关系:菱形继承,例如下面给出的代码:
class Person
{
public:int _ads;};class Professor : public Person
{
public:int _age;string _name;
};class Teacher : public Person
{public:int _tele;
};class Student : public Professor, public Teacher
{
public:int _weight;
};
其结构可由下图表示:
对于菱形继承,其存在着一个问题,即数据冗余和二义性。这是因为在父类中,声明了成员变量_。
对于和这两个类中分别继承了。对于,分别继承了。因此,在中,存在着两个相同的成员变量_。对于这点,也可以在监视窗口进行查看:
由于存在着两个相同的成员变量,因此造成了数据冗余。至于二义性。则体现在对于这个成员变量进行访问时所体现,例如:
通过上面给出的图片可以看出,此时编译器并不知道,需要访问的变量_是从哪个父类继承而来的,因此造成了二义性。但是,可以通过显式访问的方法来解决二义性问题,即:
int main()
{Student s;s.Professor::_ads = 10;s.Teacher::_ads = 15;return 0;
}
不过,这种方式只能解决二义性问题,不能解决数据冗余问题。
为了解决数据冗余的问题,需要引入虚继承,具体操作如下:
class Person
{
public:int _ads;};class Professor : virtual public Person
{
protected:int _age;string _name;
};class Teacher1 : virtual public Person
{protected:int _tele;
};class Student : public Professor ,public Teacher
{
public:int _weight;
};
对于虚继承的使用原则,下面给出一个例子用于说明:
假设上图给出的结构代表一个继承体系,根据上面对与数据冗余和二义性的介绍,上图中,在中存在两个类继承过来的内容从而造成数据冗余。在使用虚继承时,造成数据冗余和二义性的源头上,例如图中,造成上述问题的源头是因为分别继承了一次。所以,在加入虚继承时,需要在继承以及继承时加上。