研究菱形虚拟继承和虚表(探索多态的原理)

1.菱形虚拟继承

继承

定义的理解
        C++中存在继承机制。通过继承,我们可以利用已存在的 数据类型来定义新的数据类型,在新的数据类型中不仅有自己新定义的成员外,还包含以前以前旧的成员,即允许程序员在保持原有类特性的情况下对其进行扩展。其中旧的类型成为基类或父类,新的类型成为派生类或子类。继承机制是面向对象程序设计中代码可以复用的最重要的 手段。
       以上是书面的解释,通俗的我们可以这样理解,好比是有一件纯白的衣服,它上面什么花色也没有,但它也是衣服,可以为人所用,这件衣服我们理解它为父类;有一天,你需要一件彩色的衣服去演出,这时你可以用一件与父类一模一样的白衣服去染色,这样就可以很容易的得到一件彩色的衣服而不用从布匹开始重新做一件衣服,这件彩色的衣服我们理解它为子类。
分类及特点
   
   


单继承、多继承以及菱形继承

单继承:一个子类只有一个直接父类

多继承:一个子类有两个及两个以上父类

菱形继承(钻石继承):

菱形继承是 继承机制中的特殊形式,由于c++的继承机制中同时允许单继承和多继承,所以便有了这种特别 的继承方式。
以下是一段菱形继承的代码:
#include<iostream>
using namespace std;
class AA
{public:
int _aa;
};
class BB:public AA
{
public:
int _bb;
};
class CC:public AA
{
public:
int _cc;
};
class DD:public BB,public CC
{
public:
int _dd;
};
int main()
{
DD d;
d.BB::_aa=0;
d.CC::_aa=1;
d._bb=2;
d._cc=3;
d._dd=4;
cout<<sizeof(d)<<endl;
system("pause");
return 0;
}

由上图我们很容易看出,菱形继承有两个缺陷:二义性、数据冗余
二义性:由于BB类和CC类同时继承了AA类,所以当DD类同时继承BB和CC类时,DD类中会包含两份AA类成员,当DD类调用其成员时,会难以分辨到底是使用哪一个AA类成员。
数据冗余:由于DD类包含两份AA类成员,所以存在数据的重复和冗余。
       解决它们的方法有两种:一种是使用访问限定符,不过这种方式只能解决二义性,程序中仍然存在数据冗余的情况,所以在这里不做赘述。
本篇我们重点分析第二种解决方法——虚继承
代码如下:
#include<iostream>
using namespace std;
class AA
{public:
int _aa;
};
class BB:virtual public AA
{
public:
int _bb;
};
class CC:virtual public AA
{
public:
int _cc;
};
class DD:public BB,public CC
{
public:
int _dd;
};
int main()
{
DD d;
d.BB::_aa=0;
d.CC::_aa=1;
d._bb=2;
d._cc=3;
d._dd=4;
cout<<sizeof(d)<<endl;
system("pause");
return 0;
}


                                                                                                                                  共24字节
此时BB类和CC类中不再存AA类的实际成员,而是存储其自身成员相对于AA类成员的偏移量的地址额的前4字节的地址
当调用DD类成员时,可根据偏移地址找到AA类,这样就解决了二义性和数据冗余的问题。
但特别要说明的是,在我们现实生活中,我们要尽量避免这种情况的发生,一般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使用虚继承解决数据冗余问题的同时也带来了性能上的损耗。

2.虚表(探索多态的原理)

虚函数:类的成员函数前面加virtual关键字,则这个成员函数称为虚函数。 
虚函数重写:当在子类的定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写(也称覆盖)了父类的这个虚函数。
多态:
       ①使用虚函数的重写来实现多态。
       ②返回值、函数名、参数要一致(协变除外)
           


        当使用基类的指针或引用调用重写的虚函数时,指向父类调用的就是父类的虚函数,指向子类调用的就是子类的虚函数。

  

通过调试我们可以看出实际上类里的虚函数都是在虚函数表中以地址的方式保存。通过虚表指针来查找虚函数。

由于本人学术不精,若有错误,请在评论中指正,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值