当前位置: 首页 > news >正文

虚基表与虚继承的内存关系

虚基表与虚继承的内存关系

一、虚继承的核心机制

虚继承通过虚基表(vbtable)虚基类指针(vbptr)来实现,确保菱形继承中只有一份虚基类副本。

二、内存结构对比

2.1 普通继承(无虚继承)的内存布局

classPerson{public:string name;// 假设 32 字节(64位系统)intage;// 4 字节};classTeacher:publicPerson{public:string course;// 32 字节};classStudent:publicPerson{public:intstuId;// 4 字节};classTeachingAssistant:publicTeacher,publicStudent{public:string dept;// 32 字节};

内存布局图解:普通菱形继承的内存布局(无虚继承)


2.2 虚继承的内存布局

classPerson{public:string name;// 32 字节intage;// 4 字节};// 虚继承classTeacher:virtualpublicPerson{public:string course;// 32 字节};classStudent:virtualpublicPerson{public:intstuId;// 4 字节};classTeachingAssistant:publicTeacher,publicStudent{public:string dept;// 32 字节};

虚继承内存布局图解

三、虚基表(vbtable)的结构

3.1 虚基表的内容

// 虚基表的结构(概念上)structVirtualBaseTable{ptrdiff_t offset_to_top;// 到对象顶部的偏移ptrdiff_t offset_to_virtual_base;// 到虚基类的偏移// 可能还有多个虚基类的偏移};

虚基表(vbtable)结构

TeachingAssistant 对象的虚基表 Teacher 的虚基表 (通过 Teacher::vbptr 指向) offset_to_top = 0 ← 从 Teacher 部分到对象顶部 offset_to_Person = 72 ← 到 Person 部分的偏移 ↑ Teacher::vbptr ─────┘ Student 的虚基表 (通过 Student::vbptr 指向) offset_to_top = -40 ← 从 Student 部分到对象顶部 offset_to_Person = 32 ← 到 Person 部分的偏移 ↑ Student::vbptr ────────┘

四、完整的内存偏移示例

#include<iostream>usingnamespacestd;classPerson{public:string name;intage;Person():name("Person"),age(0){}virtual~Person(){}};classTeacher:virtualpublicPerson{public:string course;Teacher():course("Math"){}};classStudent:virtualpublicPerson{public:intstuId;Student():stuId(100){}};classTeachingAssistant:publicTeacher,publicStudent{public:string dept;TeachingAssistant():dept("CS"){}};intmain(){TeachingAssistant ta;char*base=(char*)&ta;cout<<"=== 详细地址信息 ==="<<endl;cout<<"对象起始地址: "<<(void*)base<<endl;cout<<"Teacher 地址: "<<(void*)(Teacher*)&ta<<endl;cout<<"Student 地址: "<<(void*)(Student*)&ta<<endl;cout<<"Person 地址: "<<(void*)(Person*)(Teacher*)&ta<<endl;cout<<"\n=== 相对于对象起始的偏移 ==="<<endl;cout<<"Teacher 偏移: 0 字节"<<endl;cout<<"Student 偏移: "<<((char*)(Student*)&ta-base)<<" 字节"<<endl;cout<<"Person 偏移: "<<((char*)(Person*)(Teacher*)&ta-base)<<" 字节"<<endl;cout<<"\n=== 子对象之间的偏移 ==="<<endl;cout<<"Teacher → Person: "<<((char*)(Person*)(Teacher*)&ta-(char*)(Teacher*)&ta)<<" 字节"<<endl;cout<<"Student → Person: "<<((char*)(Person*)(Teacher*)&ta-(char*)(Student*)&ta)<<" 字节"<<endl;return0;}

典型输出(86位系统)

五、虚基表访问过程

5.1 通过 vbptr 访问虚基类成员

// 源代码ta.name="张三";// 编译器转换后的伪代码// 1. 通过 Teacher::vbptr 找到虚基表// 2. 从虚基表中读取到 Person 的偏移量// 3. 计算 Person 的实际地址// 4. 访问 name 成员// 等价于:ptrdiff_t offset=pTA->Teacher::vbptr->offset_to_Person;Person*pPerson=(Person*)((char*)pTA+offset);pPerson->name="张三";

访问流程图解

ta.name = "张三"; 步骤1:获取 Teacher 部分的 vbptr vbptr = ta.Teacher::vbptr (指向虚基表) 步骤2:从虚基表读取偏移量 offset = vbptr->offset_to_Person (例如 128 字节) 步骤3:计算 Person 的实际地址 pPerson = (char*)&ta + offset 步骤4:访问成员 pPerson->name = "张三"

六、虚继承的开销总结

开销类型普通继承虚继承
内存开销无额外开销每个虚基类子对象有一个 vbptr(8字节)
时间开销直接访问通过 vbptr 间接访问(多一次内存访问)
构造开销简单复杂(需要初始化 vbptr)
代码复杂度简单复杂

七、总结

概念说明
vbptr(虚基类指针)每个虚继承的子对象中存储,指向虚基表
vbtable(虚基表)存储虚基类相对于当前对象的偏移量
偏移量从当前对象起始位置到虚基类起始位置的距离
访问方式通过 vbptr → 虚基表 → 偏移量 → 计算地址 → 访问成员
主要目的解决菱形继承中的数据冗余和二义性问题
http://www.jsqmd.com/news/1175812/

相关文章:

  • GeoNet高级应用:Cityscapes数据集预训练与跨场景迁移学习
  • 深夜出图总失败?:紧急修复Midjourney氛围崩坏的4种实时诊断法——从seed漂移到--s参数过载全链路排查
  • PARD-Qwen3-0.6B模型架构详解:从Qwen3到PARD优化的完整技术栈
  • 如何为Inventory Kamera添加新角色支持:开发者手动更新数据库指南
  • 多模态能力深度探索:Qwen3.5-397B-A17B-NVFP4图文视频输入处理完整教程
  • 跨省运电动车,真不用拆电池?2026线上办理全流程实测 - 快递物流资讯
  • 分子改性抗老化技术落地:盖茨皮带工业传动特种工业皮带设计原理
  • 开发者必看:Qwopus3.6-35B-A3B-Coder-bf16工具调用与函数生成实战教程
  • 紧急预警:ChatGPT低效提问正在 silently erode 你的生产力——3天内必须掌握的4个止损型提问范式
  • 7 月实地测评广州连锁珠宝铺,拆解缺配件恶意折价回收全套圈套 - 每日生活报
  • HarmonyOS旅行探索——城市详情页的结构化信息展示
  • 票据遗失怎么线上登报?足不出户线上提交刊登全流程~ - 点办通
  • Prompt 工程已死?我转投 Agent Loop 后的真实感受
  • 可灵AI 30亿美元融资深度解析:BAT同台、180亿美元估值、12个月IPO倒计时,AI视频赛道的资本终局之战
  • Nav2 核心参数配置 yaml 模板说明
  • 基于go2_ros2_sdk的SLAM与导航:Unitree GO2机器人自主移动开发终极教程
  • 免注册隐私恋爱人格测试 TOP5 大盘点,全方位剖析原生情感性格 - 独家d资讯
  • M87模型许可证解析:Apache-2.0许可下的商用与二次开发完整指南
  • 2026年惠阳黄金回收推荐解析:资质与服务维度盘点 - 生活测评小能手
  • UE4官方鱼类资源包实战:从导入到性能优化的完整指南
  • 如何解决React Native Text Input Mask常见问题:兼容性、性能优化与测试策略终极指南
  • Open Source Candies版本控制服务深度评测:GitHub、GitLab、BitBucket对比
  • 企业Agent的Tool Use安全设计:沙箱执行、权限收敛与审计日志
  • 给数据库雇一个AI数据分析师:开源神器 Vanna 实战指南
  • raf 测试策略:如何编写可靠的动画帧单元测试和集成测试?
  • 如何在React Native中实现完美输入掩码?react-native-text-input-mask快速上手教程
  • 6S是管理基石 | 杨逢昌回顾:在广东职业技术学院推行“精益6S”的实战复盘
  • Python 宏观经济实证 · 空间结构差异 - 动态分析 (1)
  • 超越传统方法:Harmonizer在自动驾驶场景重建中的突破性表现
  • 奢二网专属线下钻石回收门店,广州全域免费上门 4C 仪器鉴定裸钻 - 每日生活报