全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

c++中的虚拟继承(virtual inheritance)实现原理_c++菱形继承的vtable布局【底层】

虚拟继承确保菱形继承中虚基类子对象唯一存在,由最派生类统一构造并置于对象末尾,通过vbptr和vbase table在运行时动态定位。

虚拟继承解决的是菱形继承中基类重复实例化的问题,其核心在于让最派生类“独占”一份虚基类子对象,并通过额外的指针(virtual base pointer, vbptr)和偏移信息(virtual base offset)在运行时动态定位虚基类成员。

虚基类子对象只存在一份

在非虚拟继承的菱形结构中(如 B 和 C 都继承 A,D 继承 B 和 C),D 对象内存里会包含两份 A 的副本。虚拟继承后,B 和 C 中对 A 的继承声明为 virtual,此时编译器确保 D 中仅存在**唯一一份 A 的子对象**,且它被放置在 D 对象布局的末尾(或靠近末尾)区域,而非嵌入在 B 或 C 子对象内部。

这意味着:

  • B 和 C 子对象内部不再包含 A 的数据成员,只保留一个 vbptr(指向虚基类表 vbase table)
  • D 的构造函数负责构造唯一的 A 实例,并调整所有中间类(B/C)中的 vbptr,使其能正确定位到该 A 实例
  • 访问 A 的成员时,需通过 vbptr + 偏移量间接计算地址,无法在编译期直接确定

vtable 中新增虚基类表指针(vbptr)和虚基类表(vbase table)

每个含虚基类的类(如 B、C)的对象头部(或特定位置)会多出一个指针:vbptr。它指向一张只读的虚基类表(vbase table),该表按虚基类声明顺序存放若干 偏移量(offset to virtual base)。

例如:

  • 假设 class B : virtual A,则 B 的 vbase table 第一项是 “从 B 对象地址到 A 子对象的字节偏移”
  • class D : B, C,D 的对象中,B 子对象和 C 子对象各自带自己的 vbptr;两者指向的 vbase table 内容可能不同,但最终都导向同一份 A 实例
  • 这个偏移值在 D 构造时由编译器生成并填入——因为只有最派生类知道 A 究竟被放在哪

构造顺序与偏移修正由最派生类控制

虚基类 A 的构造由最派生类 D 的构造函数**直接调用**(跳过 B 和 C 的构造函数中对 A 的调用),这是关键语义规则。同时,D 的构造函数体执行前,会先完成:

  • 为 A 分配空间(在 D 对象内某处)
  • 计算 A 相对于 B 子对象起始地址的偏移,并写入 B 的 vbptr 所指的 vbase table 对应项
  • 同理处理 C 的 vbptr

因此,B::func() 中若访问 A::x,实际执行的是:读 B->vbptr → 查 vbase table 得 offset → (char*)this + offset → 访问 x。整个过程比普通继承多一次查表+地址计算,有轻微开销。

典型 vtable / 对象布局示意(简化)

以 GCC/Itanium ABI 为例,D 对象内存大致如下(低地址→高地址):

  • [B 子对象]:vptr_B(指向 B 的 vtable)、B 自有成员、vbptr_B(指向 B 的 vbase table)
  • [C 子对象]:vptr_C、C 自有成员、vbptr_C
  • [A 子对象]:A 的数据成员(唯一一份)

B 的 vtable 除普通虚函数外,还隐含一个“虚基类偏移字段”,但更常见的是:vtable 末尾或单独存 vbase table,其中条目为 相对于当前子对象起始地址的偏移。比如 vbptr_B 指向的表中存着 +24,表示 A 子对象起始地址 = (char*)&b_obj + 24。

基本上就这些。虚拟继承不是语法糖,它改变了对象布局模型,引入了运行时间接寻址,但也换来语义上的唯一性和可预测性。理解它,关键是抓住“最派生类统一安置 + vbptr 动态导航”这一机制。


# 字节  # c++  # 构造函数  # char  # 指针  # 继承  # 虚函数  # class  # pointer  # 对象  # this  # table  # 的是  # 派生类  # 相对于  # 唯一一  # 中对  # 自己的  # 这是  # 这一  # 偏移量  # 放在 


相关文章: 大型企业网站制作流程,做网站需要注册公司吗?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  黑客入侵网站服务器的常见手法有哪些?  香港服务器网站推广:SEO优化与外贸独立站搭建策略  哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?  浅谈Javascript中的Label语句  建站VPS能否同时实现高效与安全翻墙?  宝塔建站无法访问?如何排查配置与端口问题?    如何通过万网虚拟主机快速搭建网站?  相册网站制作软件,图片上的网址怎么复制?  如何在建站宝盒中设置产品搜索功能?  西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?  建站之星如何取消后台验证码生成?  官网自助建站平台指南:在线制作、快速建站与模板选择全解析  ,石家庄四十八中学官网?  定制建站平台哪家好?企业官网搭建与快速建站方案推荐  微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?  开源网站制作软件,开源网站什么意思?  如何在Windows服务器上快速搭建网站?  如何获取上海专业网站定制建站电话?  C#怎么使用委托和事件 C# delegate与event编程方法  可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?  如何通过山东自助建站平台快速注册域名?  青浦网站制作公司有哪些,苹果官网发货地是哪里?  建站之星24小时客服电话如何获取?  python的本地网站制作,如何创建本地站点?  建站之星好吗?新手能否轻松上手建站?  在线制作视频的网站有哪些,电脑如何制作视频短片?  如何用腾讯建站主机快速创建免费网站?  宁波自助建站系统如何快速打造专业企业网站?  郑州企业网站制作公司,郑州招聘网站有哪些?  如何选择香港主机高效搭建外贸独立站?  如何在VPS电脑上快速搭建网站?  高防服务器租用首荐平台,企业级优惠套餐快速部署  建站之星后台管理系统如何操作?  番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?  如何在阿里云购买域名并搭建网站?  建站为何优先选择香港服务器?  婚礼视频制作网站,学习*后期制作的网站有哪些?  网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?  ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?  详解jQuery中基本的动画方法  长春网站建设制作公司,长春的网络公司怎么样主要是能做网站的?  C++时间戳转换成日期时间的步骤和示例代码  如何快速完成中国万网建站详细流程?  如何快速搭建响应式可视化网站?  存储型VPS适合搭建中小型网站吗?  电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?  如何快速搭建FTP站点实现文件共享? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。