虚拟继承

上一篇我们已经讨论了继承体系下派生类的对象模型https://blog.csdn.net/a15929748502/article/details/80893870

这一篇我们来解决上一篇中提出的问题:在菱形继承里,B的成员变量在D中存了两份,这显然是不合理的,不仅浪费了空间,还产生了二义性,如何避免这种事情的发生呢,这就是接下来要讨论的问题

这里就不得不提到今天的主题虚拟继承

虚拟继承的作用;针对上片的问题具体说虚拟继承可以在上述情况中起到节省空间的作用,同时也解决了二义性问题,它会让B成为一个虚拟基类被C1和C2继承,这时D再继承C1,C2,这时D就只会保存一份B中的成员了。

也就是说他可以解决从不同途径继承来的同一基类,会在子类中存在多份拷贝,浪费空间,并且产生二义性的问题

虚拟继承的格式:

class   子类名称:virtual   继承权限    父类名称

 {

           。。。。。。

};   

它是通过什么方式解决呢,我们通过学习可以知道一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间,4字节)和虚基类表(不占用类对象的存储空间)(需要强调的是,虚基类依旧会在子类里面存在拷贝,只是仅仅最多存在一份而已,并不是不在子类里面了);当虚继承的子类被当做父类继承时,虚基类指针也会被继承。其中虚基类指针就指向虚基类表。

而虚表中就记录着直接继承类相对于自己的偏移量,和虚基类相对直接继承类的偏移量。

 

我们可以用代码来验证一下

#include <iostream>
using   namespace    std;
class B
{
        public:
                int _b;
};
class C1:virtual public B
{
        public:
                int _c1;
};
class C2 :virtual public B
{
        public:
                int _c2;
};
class D : public C1, public C2
{
        public:
                int _d;
};

int main()
{
        D  d;
        d._b=1;
        d._c1=2;
        d._c2=3;
        d._d=4;
        cout<<*(int*)&d<<endl;
        cout<<*((int*)&d+1)<<endl;
        cout<<*((int*)&d+2)<<endl;
        cout<<*((int*)&d+3)<<endl;
        cout<<*((int*)&d+4)<<endl;
        cout<<*((int*)&d+5)<<endl;

        cout << sizeof(B) << endl;       //4
        cout << sizeof(C1) << endl;      //12
        cout << sizeof(C2) << endl;      //12           
        cout << sizeof(D) << endl;       //24
        return 0;
}

 

运行一下

 

 
[root@localhost C++]# ./a.out
134515356
2
134515368
3
4
1
4
12
12
24

 

 

可见我们的猜想是正确的

 

 

我们可以画出对象模型

这就是虚拟继承的对象模型

可以看出虚基类在对象模型的最下面。

这样的模型有什么好处呢,于普通继承有有什么差别

1,从访问方面

普通继承直接访问

虚拟继承通过虚基类表中的偏移量来访问(这是解决问题的关键)

2,构造函数

普通继承没有系统合成的构造函数

虚拟继承有系统合成的构造函数将偏移量表格地址放对象前四个字节,多一个参数检测是否为虚拟继承。

3,对象模型

 

普通继承基类在最上,继承类在下。

虚拟继承(虚)基类在最下,而派生类在上。

如图

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值