虚函数和虚继承的深入调查

这两天在研究虚函数和虚继承的时候发现很多有意思的情况,后来通过查看博客和内存分布大致总结了一下关于虚函数和虚继承间的一些东西。在写之前先记录下VS下查看内存分布的命令。通过项目->属性->C/C++->命令行输入/d1 reportAllClassLayout 。然后按F7运行即可查看内存分布情况。

下面介绍一下基类中含有虚函数,不含虚函数情况下普通继承和虚继承的情况。

1、首先是普通继承的情况 :这时不管子类是否重写了父类虚函数,或者是否含有新的虚函数,子类中都只有一个虚函数指针指向自己的虚函数表。其中子类虚函数表的第一个函数是B::funA(),第二个是B::funB();

2、当子类虚继承父类时,子类一定会生成一个虚基类指针。其次,若父类有虚函数指针则拷贝。最后,若自己有新的虚函数则会产生一个新的子类的虚函数指针,若只是重写了父类的虚函数,则只会继承父类的虚函数指针而不会产生自己的虚函数指针。如下图所示:

 

这时sizeof(B)=8; 

 

 

这时sizeof(B)=12;

3、普通多继承的情况

在普通多继承且父类有虚函数的情况下,子类只会继承父类的虚函数指针并不会生成新的自己的虚函数指针。若自己有新的虚函数,会将新的虚函数地址放置在第一个继承的父类的虚函数指针指向的虚函数表的最后。

 

 

sizeof(C)=8;并且funC函数放置在了funA函数之后。 

4、多重继承+虚继承

在上面这种情况下,考虑若都为虚继承的情况下,肯定会产生一个虚基类指针指向他的基类A和B,然后分别继承父类的虚函数指针,最后根据自己是否有新的虚函数来决定是否产生新的自己的虚函数指针。

 

sizeof(C)=12; 

 

 

sizeof(C)=16; 

5、菱形继承情况下的三种情况:

      (1):直接继承和间接继承间都是普通继承:

 

这样 sizeof(D)=16;原因在于A的成员数据a拷贝了两份。但是虚函数指针只是简单继承了B和C的虚函数指针。

    (2):中间父类是虚继承,最后是普通继承

 

sizeof(D)=20;可以看出来这时B和C都有3个指针,分别是自己的虚基类指针、自己的虚函数指针、A的虚函数指针。但是D继承时A的虚函数指针只继承一份,其他的全部继承下来。若A中有数据成员的话,D中也只会存在一份,这样就避免了多重继承下的二义性问题。

    (3):所有情况下都是虚继承

 

 

sizeof(D)=28;这时因为是虚继承并且D中也有自己新的虚函数,所有会多创建一个虚基类指针和一个新的虚函数指针。

 

总结:

父类中有虚函数时会产生一个虚函数指针,若子类单继承时会继承父类的这个指针,若自己有新的虚函数也会将函数地址放在此虚函数指针所指虚函数表的最后。多继承时会同时继承多个虚函数指针,可以寻址多个虚表。这时自己的虚函数会将函数地址放在第一个继承来的虚函数指针指向虚表的最后。

在虚继承的情况下,不管是单继承还是多继承,子类都会创建一个虚基类指针,指向一个虚基类表。此外子类会继承父类的虚函数指针,当子类仅重写父类虚函数的情况下,不会创建新的虚函数指针。一旦子类有自己的虚函数,则子类会创建一个新的虚函数指针指向一个新的虚函数表,内部保存自己的虚函数的地址。

以上实验均在VS2015平台下做,linux g++编译器编译结果有可能有出入。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值