C++ 多重继承下的内存布局
1. 多重继承
多重继承示例代码如下:
class Base1 {
public:
void f0() {}
virtual void f1() {}
int a;
};
class Base2 {
public:
virtual void f2() {}
int b;
};
class Derived : public Base1, public Base2 {
public:
void d() {}
void f2() {} // override Base2::f2()
int c;
};
int main() {
Base2 *b2 = new Base2;
Derived *d = new Derived;
}
答案是不行
2. top offset
在此,先给出结论:将对象从当前这个类型转换为该对象的实际类型的地址偏移量。
Vtable for Derived
Derived::_ZTV7Derived: 7u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 (int (*)(...))Base1::f1
24 (int (*)(...))Derived::f2
32 (int (*)(...))-16
40 (int (*)(...))(& _ZTI7Derived)
48 (int (*)(...))Derived::_ZThn16_N7Derived2f2Ev
class Base1和class Base2两个类的虚函数表拼接而成 。因为是多重继承,所以编译器将先继承的那个认为是 主基类(primary base)
在多继承中,当最左边的类中没有虚函数时候,编译器会将第一个有虚函数的基类移到对象的开头,这样对象的开头总是有vptr。
首先看虚函数表的前半部分,如下:
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 (int (*)(...))Base1::f1
24 (int (*)(...))Derived::f2
接着看虚函数表的下半部分:
32 (int (*)(...))-16
40 (int (*)(...))(& _ZTI7Derived)
48 (int (*)(...))Derived::_ZThn16_N7Derived2f2Ev
偏移值为-16,因为是多重继承,所以class Base1和class Base2类型的指针或者引用都可以指向class Derived对象,那么又是如何调用正确的成员函数呢?
Base2* b2 = new Derived;
b2->f2(); //最终调用Derived::f2();
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端