多继承与链式继承的内存布局及类型转换技术疑问
问题解答
1. MyClass的数据布局
答案是B,和child_n的布局完全不同。
MyClass是多继承了链式继承链中的每一个类(parent、child1、child2……child_n),每个基类都会在MyClass的内存中生成一个独立的子对象,彼此完全分开。具体内存布局按继承声明的顺序依次排列:
- 首先是
parent的子对象,对应DATA - 接着是
child1的子对象,对应DATA + extra1(注意这里的parent部分和前面的parent子对象是独立的,并非同一块内存) - 然后是
child2的子对象,对应DATA + extra1 + extra2 - ……
- 最后是
child_n的子对象,对应DATA + extra1 + extra2 + ... + extra_n
简言之,MyClass的内存是把链式继承链上每个类的完整实例依次拼接而成,和child_n单继承的叠加结构完全不同。
2. 向上转换的地址管理
编译器会在编译阶段就计算好每个基类子对象在MyClass实例中的内存偏移量,转换时直接通过偏移量计算地址,不需要额外存储每个子类的起始地址。
举个例子:
- 把MyClass指针转换为
parent*时,直接使用MyClass实例的起始地址(parent是第一个继承的基类,偏移量为0) - 转换为
child1*时,用MyClass的起始地址加上parent子对象的大小 - 转换为
child2*时,用MyClass的起始地址加上parent + child1子对象的总大小 - ……
所有偏移量都是编译期确定的,运行时仅需做简单的地址加法,就能得到对应基类子对象的指针。
内容的提问来源于stack exchange,提问作者Crackie
相关产品推荐
相关产品推荐

