1:分析菱形继承的问题。
2:剖析虚继承是怎么解决二义性和数据冗余的。
首先我们来看看什么是继承?
继承是面向对象复用的重要手段。通过继承定义一个类,子类共享父类继承下来的成员。
继承的方式有:public,private,protected
总结:
总结:
1.基类的私有成员在派生类中是不能被访问的,如果一些基类成员在类外不想被基类对象直接访问,但需要在派生类中能访问,就定义为保护的。可以看出保护成员限定符是因为继承才出现的。
2.public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也是一个父类对象。也就是说,我就是一个你,我包含着你。
3.不管是哪种继承方式,在派生类内部都可以访问积累的共有成员和保护成员,但是基类的私有成员在子类中不可见,就是不能访问,但是也继承下来了。
4.使用关键字class时默认的继承方式是private,使用关键字struct时默认public,不过最好显示的写出继承方式。
2.public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也是一个父类对象。也就是说,我就是一个你,我包含着你。
3.不管是哪种继承方式,在派生类内部都可以访问积累的共有成员和保护成员,但是基类的私有成员在子类中不可见,就是不能访问,但是也继承下来了。
4.使用关键字class时默认的继承方式是private,使用关键字struct时默认public,不过最好显示的写出继承方式。
我们先来看一个菱形继承的程序。
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
string _name;
};
class Student:public Person
{
public:
string _id;
};
class Teacher:public Person
{
public:
string _num;
};
class Assistant:public Student,public Teacher
{
public:
string _majorcourse;
};
void Test()
{
Assistant a;
a.Student::_name = "yangpanting";//需要显示指定访问的父类Student
a.Teacher::_name = "xujinghang";//需要显示指定访问的父类Teacher
}
int main()
{
Test();
}
Assisitant的对象中有两份Person成员,导致继承存在二义性和数据冗余的问题。
为了解决以上问题,我们引入了虚继承的语法,可以有效的解决数据冗余和二义性的问题。
虚继承解决了菱形继承体系里的子类对象包含多份父类对象的成员。
下面我们以简单的代码通过监视窗口更加清楚地剖析:
class A
{
public:
int _a;
};
class B:public A
{
public:
int _b;
};
class C:public A
{
public:
int _c;
};
class D:public B,public C
{
public:
int _d;
};
int main()
{
D d;
d._a = 2;
d._b = 4;
d._c = 5;
d._d = 6;
return 0;
}
菱形继承:
菱形继承的对象模型:
剖析如下:
总结:虚继承解决了在菱形继承中的子类对象包含多份父类对象的数据冗余和浪费空间的问题。
但一般,在实际应用中我们一般不会定义如此复杂的结构,不到万不得已我们是不会用菱形继承的,因为它解决了数据冗余问题的同时,也带来性能上的损耗。
!