C++多态多重继承与虚继承结合时对内存布局(sizeof)的影响

参考文献:《深度探索C++对象模型》

                     https://bbs.youkuaiyun.com/topics/390083150

                     https://blog.youkuaiyun.com/u011841639/article/details/39156347

运行平台:Visual Studio 2015(32bits

我在上一篇博客(https://blog.youkuaiyun.com/m0_38014304/article/details/84286266(看了这一篇就不用看上一篇了)中探讨了C++中虚继承对类的sizeof大小的影响,而当虚继承与多重继承、多态联系在一起时,其sizeof的结果使得我又产生了困惑。这次我关于类中编译器附加的“虚函数表指针”和“虚基类指针”进行了相关研究,主要针对存在多态的虚继承的对象模型,在此特别感谢大佬(https://blog.youkuaiyun.com/u011841639/article/details/39156347)所给的启发,我们开始吧。

源码:

<think>嗯,用户想了解C++多态的实现原理,特别是虚函数表和虚函数指针的部分。首先,我需要回忆一下多态的基本概念。多态分为编译时多态和运行时多态,这里应该是指运行时多态,也就是通过虚函数实现的动态绑定。 根据用户提供的引用资料,引用1提到每个包含虚函数的类都有一个虚函数表(VTable),编译器会把虚函数表的指针放在对象实例的最前面。引用2则详细说明了虚函数表是函数指针数组,每个元素对应虚函数的地址,并且类中存在虚函数时,对象大小会增加4字节(32位系统),也就是一个指针的大小。 接下来需要整理这些信息,分步骤解释多态的实现机制。首先,虚函数表的结构,每个类有一个,存储虚函数地址。然后,对象实例中的虚函数表指针(vptr),指向对应的vtable。当调用虚函数时,通过vptr找到vtable,再找到对应的函数地址,实现动态绑定。 需要注意的是,用户可能对虚函数表的内存布局不太清楚,可以结合引用的例子,比如CTest类的大小变化,说明vptr的存在。此外,可能需要解释继承情况下的虚函数表,比如派生类如何覆盖虚函数,以及多重继承下的情况,不过用户的问题可能更关注基础的单继承情况。 另外,用户可能想知道为什么虚函数能够实现多态,这里需要强调动态绑定和静态绑定的区别。普通函数调用在编译时确定地址,而虚函数在运行时通过vtable查找,这才能实现根据对象类型调用正确的函数。 还需要注意代码示例是否必要,用户提供的引用中有C++代码,可以引用来说明类的结构,但用户的问题是关于原理,可能需要用更简洁的示例或者描述来解释。 最后,生成相关问题时要围绕多态、虚函数表、内存布局、性能影响等方面提问,确保问题有助于用户深入理解。</think>### C++多态的实现原理 #### 1. 虚函数表(vtable)的核心作用 每个包含虚函数的类都会自动生成一个**虚函数表**(Virtual Table),这个表本质上是一个**函数指针数组**。数组中每个元素对应类中虚函数的地址,例如: ```cpp class Animal { public: virtual void speak() { cout << "Animal sound" << endl; } virtual ~Animal() {} }; ``` 此时`Animal`类的虚函数表中包含`speak()`和析构函数的地址[^2]。 #### 2. 虚函数指针(vptr)的内存布局 当类包含虚函数时: - 编译器会在**每个对象实例头部**插入一个隐藏的虚函数表指针(vptr) - 该指针指向对应类的虚函数表 - 验证方法: ```cpp cout << sizeof(Animal) << endl; // 输出4(32位系统)或8(64位系统) ``` 当类没有虚函数时,对象大小为1字节(空对象占位符),添加虚函数后大小变为指针尺寸。 #### 3. 多态调用过程 ```cpp Animal* animal = new Dog(); animal->speak(); // 动态绑定到Dog::speak() ``` 具体执行步骤: 1. 通过对象地址找到vptr 2. 通过vptr访问虚函数表 3. 在虚函数表中找到speak()的偏移位置 4. 调用对应的函数指针 #### 4. 继承体系下的虚函数表 当存在继承关系时: ```cpp class Dog : public Animal { public: void speak() override { cout << "Woof!" << endl; } }; ``` - `Dog`类会复制父类的虚函数表 - 覆盖重写的虚函数条目 - 新增的虚函数会追加到虚函数表末尾 #### 5. 虚函数表特性总结 | 特性 | 说明 | |-----------------------|----------------------------------------------------------------------| | 编译期生成 | 每个类有且仅有一个虚函数表 | | 内存位置 | 通常存储在程序的只读数据段 | | 动态绑定成本 | 多一次指针解引用操作(约2-3个CPU周期) | | 多重继承 | 每个基类对应独立的虚函数表指针 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值