虚函数、虚继承

前言:对于Virual关键字的使用情况之前一直是似懂非懂的。这次在复习过程中又一次遇到了有关派生类虚继承之后的在内存中所占的大小。其实之前看书的时候也曾几次遇到过类似有关virtual的问题,每一次总感觉自己当下似是理解了,结果事后遇到类似的又再一次卡壳,可见还有很多知识是需要自己不断去理解并掌握的。蹭着这次遇到的问题,在同学的帮助下,并结合网上早前就已有很多人对此做了很多探讨。好记性不如烂笔头,特此将这些独到的见解收藏一番。

虚函数与虚继承寻踪 》(全文阅读请点击此处

此篇技术博文图文并茂的为我们分析了以下几种情况:

  • 简单类情况下的对象结构
  • 普通单重继承后派生类的对象结构
  • 普通多重继承后派生类的对象结构
  • 虚拟继承下的多重继承后的派生类的对象结构

此处,摘其小结:

  • 当类中包含虚函数时,则该类每个对象中在内存分配中除去数据外还包含了一个虚函数表指针(vfptr),指向虚函数表(vftable),虚函数表中存放了该类包含的虚函数的地址。
  • 当子类通过虚继承的方式从父类中派生出来,此时称父类为子类的虚基类。子类中将包含虚基表指针(vbptr),指向虚基类表(vbtable)
  • 在单继承形式下,子类将完全获得父类的虚函数表和数据(假入父类中有虚函数的话)。如果子类中重写了父类的虚函数,就会在虚函数表中原本记录父类中虚函数的地址覆盖为子类中对应的重定义后的该函数地址,否则不做变动。如果在子类中定义了新的虚函数,则虚函数表中会追加一条记录,记录该函数的地址(虚函数表中是顺序存放虚函数地址的,记住,虽然虚函数表中添加了内容,但是此时对于该类的大小来说并未发生改变,因为始终只有一个指向虚函数表的指针vfptr)。
    注意:
    如果在派生类对象直接访问自身中的重定义的虚函数是不会触发多态机制的,因为这个函数调用在编译时期是可以确定的,编译器只需要直接调用即可;
    当对父类指针赋予不同的子类指针时,在调用子类中重定义的虚函数时才会触发多态机制,即动态的在运行期间调用属于子类的该函数。(可适度地了解下覆盖override和重载overload的区别)
  • 在多重继承形式下,派生类会把所有的父类按继承时的顺序包含在自身内部。每个父类对应一个单独的虚函数表。多重继承下,子类不再具有自身的虚函数表,它的虚函数表与第一个父类的虚函数表合并了。同样的,如果子类重写了任意父类的虚函数,都会覆盖对应的函数地址记录。如果MyClassC重写了fun函数(两个父类都有该函数),那么两个虚函数表的记录都需要被覆盖!

    此时由于多重继承下将存在对公共基类的多份拷贝问题,为了节省内存空间,故而出现了虚拟继承,那么将只生成一个共享的基类。

  • 虚继承的引入把对象的模型变得复杂,除了每个基类和公共基类的虚函数表指针vfptr需要记录外,每个虚拟继承了的父类还需要记录一个虚基类表vbtable的指针vbptr。

  • 虚基类表每项记录了被继承的虚基类子对象相对于虚基类表指针的偏移量。

    原文的举例和作图相呼应,十分出彩,极力推荐感兴趣者通读原文,此处我也只是用自己的方式做下笔记而已,不喜勿喷,谢谢~

    扩展:
    纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。


    献上另一篇文章可一起了解:C++虚函数表解析

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值