虚函数和虚表

张开发
2026/4/16 3:40:03 15 分钟阅读

分享文章

虚函数和虚表
为什么需要虚函数先看一个没有虚函数的例子class Base { public: void show() { cout Base::show endl; } }; class Derive : public Base { public: void show() { cout Derive::show endl; } }; int main() { Base* p new Derive(); p-show(); }输出是什么Base::show原因很简单普通成员函数的调用在编译期就确定了静态绑定编译器只看指针类型Base*。但现实需求是“用父类指针指向子类对象调用子类的实现”这就是运行时多态。什么是虚函数class Base { public: virtual void show() { cout Base::show endl; } };虚函数的本质函数调用的目标在运行期决定而不是编译期一旦函数被virtual修饰调用方式从静态绑定变成动态绑定运行时绑定虚表到底是什么虚表是啥虚表是一个函数指针数组里面存的不是数据而是虚函数的真实函数地址虚表是谁的每个“类”有一张虚表每个“对象”有一个虚表指针对象内存布局class Base { public: virtual void f1() {} virtual void f2() {} int a; };对象在内存中的结构Base 对象------------------| vptr | --- 指向 Base 的虚表------------------| int a |------------------Base 的虚表只存在一份Base::vtable------------------| Base::f1 |------------------| Base::f2 |------------------继承 虚表class Base { public: virtual void f1() { cout Base::f1\n; } virtual void f2() { cout Base::f2\n; } }; class Derive : public Base { public: void f1() override { cout Derive::f1\n; } virtual void f3() { cout Derive::f3\n; } };派生类的虚表结构Derive::vtable------------------| Derive::f1 | // 覆盖 Base::f1------------------| Base::f2 | // 继承的------------------| Derive::f3 | // 新增的虚函数------------------虚函数表是“覆盖不是追加在父类后面乱放”虚函数调用的底层流程对象 → vptr → vtable → 函数地址 → 调用展开就是通过对象首地址找到vptr通过vptr找到虚表根据虚函数在表中的偏移找到函数指针调用函数

更多文章