虚函数表(VTable)是C++实现运行时多态的核心机制,每个含虚函数的类有静态函数指针表,按声明顺序存虚函数地址;每个对象头部隐式存储vptr指向所属类VTable;虚函数调用编译为“读vptr→查表→跳转”,支持单/多重/虚继承下的动态绑定。

虚函数表(VTable)是C++实现运行时多态的核心机制,它让基类指针或引用能调用派生类的重写函数——不是靠编译期决定,而是靠对象内存中隐藏的函数地址跳转来完成。
每个含虚函数的类都有一个VTable
编译器为每个定义了虚函数(或继承了虚函数)的类生成一张静态的函数指针表。这张表里按声明顺序存放着该类所有虚函数的实际地址(即最终要执行的函数入口)。比如:
Base 类有 virtual void foo() 和 virtual void bar(),它的 VTable 就有两个指针,分别指向 Base::foo 和 Base::bar 的代码段;Derived 继承 Base 并重写了 foo(),那么 Derived 的 VTable 中第一个指针就换成 Derived::foo 的地址,第二个仍为 Base::bar(除非也被重写);如果 Derived 新增了虚函数 virtual void baz(),这个函数地址会追加到 VTable 末尾。
每个对象头部隐式存储一个vptr(虚函数表指针)
只要类有虚函数,编译器就会在该类的每个对象最开始的位置(通常是前8字节,在64位系统上)插入一个指针 vptr,它指向所属类的 VTable。这个过程对程序员完全透明:
创建 Base b; → b 的内存开头是 &Base::vtable;创建 Derived d; → d 的内存开头是 &Derived::vtable;当用 Base* p = new Derived; 时,p 指向的是 d 的起始地址,所以 p->vptr 实际指向的是 Derived 的 VTable。
虚函数调用被编译成“查表+跳转”指令
像 p->foo(); 这样的调用,编译后不是直接 call 地址,而是三步操作:
立即学习“C++免费学习笔记(深入)”;
从 p 所指对象的首地址读出 vptr;根据 foo 在虚函数声明顺序中的索引(比如第0个),访问 vptr[0] 得到函数地址;间接 call 这个地址。
这就是为什么虚函数调用比普通函数慢一点:多了一次内存读取和一次间接跳转。但现代CPU分支预测和缓存通常能缓解这部分开销。
多重继承和虚继承会让vptr变复杂
单继承下一般只有一个 vptr;但多重继承时,派生类对象可能包含多个子对象布局,每个“基类子对象”区域都可能有自己的 vptr:
class D : public A, public B → D 对象内存中可能有 A 部分的 vptr 和 B 部分的 vptr;虚继承引入虚基类子对象,还会额外增加偏移调整逻辑(有时通过 thunk 中转函数修正 this 指针);这些细节由编译器自动生成,开发者通常只需知道“多态仍能正确工作”,不必手动管理 vptr。
基本上就这些。VTable 是静态的、类级别的;vptr 是动态的、对象级别的。两者配合,让 C++ 在零运行时反射的前提下,实现了高效的动态绑定。不复杂但容易忽略——它藏在对象内存布局最前面,默默支撑着 every virtual call。
以上就是c++++中的VTable(虚函数表)是如何工作的_c++多态实现机制【底层】的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1489807.html
微信扫一扫
支付宝扫一扫