[c++]菱形继承解析

菱形继承

  • 大概示意图:

菱形继承不一定只是标准的菱形,只要形似菱形的都可以叫菱形继承。


(以下说明都是默认公有继承,public和protected成员情况下)

菱形继承会造成数据的冗余和二义性:

  • 冗余:一个Assitant对象里面有两个Person的成员(如果成员是_name,那么就会有两个_name)
  • 二义性:如果用Assitant对象取访问_name,会报错(编译器不确定访问哪一个_name

为了处理这种情况,祖先就开发并使用了虚继承

  • 我们使用更简便的例子取讲解虚继承具体是怎么取处理的:

虚拟继承之后发现: _a 变成唯一的了,并且将_a放在了D对象组成的最下面

这时候有小伙伴就会问了,那编译器怎么取访问_a呢?而且75c和764(上图中地址的后缀)存放的又是什么呢?

  • 75c和764里面的指针就是编译器找到那个唯一_a的途径 ;75c存放的地址位置指向一个叫虚基表的东西,所以B和C中存放对应地址 的指针就叫虚基表指针;
  • 虚基表里面存放着一种叫偏移量的东西,简单来说:偏移量里面第二行存放的是,当前指针(虚基表指针 )与对象底部_a之间的地址距离。[1](#当前指针(虚基表指针)与对象底部_a之间的地址距离。1)

简图解释如下: (便于和上面相通,读者们可将A和Person视作同一个类)
到这里有同学可能就会提问:那如果A(Person)里有更多的成员变量呢?那是不是虚基表里面会存更多的偏移量?

  • 事实上并不会哦,只需要存储A类型中首个声名的成员变量的偏移量即可,找到首个后,编译器自然就会向下访问下面的成员变量。

**有同学可能会问,为什么使用虚拟继承之后,对象内占用的空间变多了? **

  • 实际上这是因为A类太小了造成的错觉,加入A类中的成员函数增加到更多个,那么再虚拟后占用就会就会清晰可见的减少:
  • 证明多个成员变量都是存在对象的底部:

  1. 75c到_a(所继承A的首个成员地址)的地址770之间差了20 (16进制下是显示的是14 ) ↩︎
相关推荐
程序猿_极客1 小时前
【2025 年最新版】Java JDK 安装与环境配置教程(附图文超详细,Windows+macOS 通用)
java·开发语言·windows·macos·jdk
一个不知名程序员www4 小时前
算法学习入门 --- 哈希表和unordered_map、unordered_set(C++)
c++·算法
二哈喇子!5 小时前
BOM模型
开发语言·前端·javascript·bom
C++ 老炮儿的技术栈5 小时前
在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”声明?
c语言·c++·windows·git·vscode·visual studio
二哈喇子!5 小时前
空指针异常
开发语言
咚为5 小时前
Rust Print 终极指南:从底层原理到全场景实战
开发语言·后端·rust
%xiao Q5 小时前
GESP C++五级-202406
android·开发语言·c++
Psycho_MrZhang5 小时前
Neo4j Python SDK手册
开发语言·python·neo4j
Traced back5 小时前
# C# + SQL Server 实现自动清理功能的完整方案:按数量与按日期双模式
开发语言·c#
Sarvartha5 小时前
C++ STL 栈的便捷使用
c++·算法