C++中虚拟继承和普通继承的区别

1.普通继承和虚拟继承区别

普通继承  虚拟继承
继承列表是否加virtual不需要需要
对象模型不同

基类部分在上,子类部分

在下

基类部分在下,子类部分在上,并且对象中多了四个字节
子类是否生成默认构造

不一定

如果基类有无参或者全缺省的构造方法子类没实现任何构造方法,则编译器一定会生成,如果基类没有定义任何构造方法,则编译器不生成

一定会生成

并且编译器在生成的构造方法中会填充对象前四个字节中的内容

子类对象访问基类成员方式      直接访问简介访问:需要借助对象前四个字节中保存的指向偏移量表格的指针,找到对应的偏移量,然后再去访问基类部分的成员

 (1)普通继承方式代码示例:

class B
{
public:
      int _b;
};

class D:public B
{
public:
      int _d;

};

int main()
{
cout << sizeof(D) << endl;  // 8
	
	D d;
	d._b = 1;
	d._d = 2; 
	return 0;
}

代码底层展示的结果:

子类访问基类成员的方式  :  直接访问

     d._b =1;   对应的汇编                                   mov           dword  ptr [d] ,1

(2)虚拟继承的代码展示:

class B
{
public:
	int _b;
};

class D :virtual public B
{
public:
	int _d;
};

int main()
{
	cout << sizeof(D) << endl; //普通继承的结果是8  虚拟继承会多四个字节 变成12字节
	
	D d;
	d._b = 1;
	d._d = 2;//赋值时候直接一条mov指令搞定
	return 0;
}

                                                                

  其中02 00 00  00对应的就是 子类新增部分的赋值

  01 00 00 00  就是基类新增部分的赋值

对于子类新增部分:

赋值时候直接一条mov指令就搞定了。

基类部分:

 给基类对象赋值时用到了三条mov指令:

第一条指令是:获取对象中前4个字节的内容:即虚基表(偏移量表格)的地址

第二条指令是:从虚基表中获取子类对象中基类部分成员存储的偏移量

第三条指令是:从基类对象位置往后偏移 offset字节,找到基类对应成员并复制

           

由上图知:子类对象从起始位置往后偏移8个字节,刚好是从基类部分继承下来成员存储的位置 

 右图也可以被称为虚基表。

由此可知多出的4个字节:这四个字节存储的是指向虚基表(偏移量表格的地址)

注意:虚拟继承只有一个作用,就是用来解决菱形继承二义性问题的---》菱形虚拟继承

                                      

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值