虚函数调用需满足三条件:函数声明为virtual、通过基类指针或引用调用、对象为多态类型;运行时通过vptr查vtable实现动态分发,构造/析构中调用虚函数不触发多态。
虚函数调用的核心在于运行时通过对象的虚表(vtable)找到实际函数地址,而不是编译期绑定。关键前提是:必须通过指针或引用,且调用的是类中声明为 virtual 的成员函数。
缺一不可:
每个含虚函数的类在编译期生成一张虚表,本质是函数指针数组。它存储该类所有虚函数的最终地址(非内联、非纯虚的函数地址;纯虚函数填 nullptr 或指向诊断函数)。
对象实例头部(通常最前面)隐式存放一个虚表指针(vptr),指向所属类的虚表。构造函数会按继承顺序设置 vptr:先调基类构造,vptr 指向基类虚表;再调派生类构造,vptr 被更新为派生类虚表。
当执行 ptr->func()(ptr 是基类指针)时:
这个过程完全在运行时完成,与指针静态类型无关,只取决于对象真实类型所决定的虚表内容。
基本上就这些。虚机制不复杂,但细节容易忽略,理解 vptr 和 vtable 的存在时机与布局,是掌握 C++ 多态底层的关键。