1. 核心概念与多态实现多态的定义多态是指“以一个接口多种实现”的能力。在 C 中通过在基类中使用virtual关键字声明函数可以实现动态绑定Dynamic Binding即在运行时根据对象的实际类型调用对应的函数。静态绑定 vs 动态绑定静态绑定在编译期确定调用哪个函数如函数重载、模板。动态绑定在运行期根据对象的虚表指针vptr寻找实际调用的函数地址。2. 底层实现机制虚表与虚指针虚函数表 (vtable)编译器为每个包含虚函数的类创建一个虚表。虚表是一个存储该类所有虚函数地址的连续内存空间类似函数指针数组。派生类如果重写了基类的虚函数虚表中对应的地址会被替换为派生类函数的地址。虚表指针 (vptr)每个包含虚函数的对象实例在内存布局的最前端会多出一个指针即虚表指针vptr。vptr 指向该对象所属类的虚表。空间代价在 64 位系统上每个对象会因为 vptr 多占 8 字节。3. 内存布局图示假设基类Base有虚函数vfunc1派生类Derive重写了它4. 关键考点与细节构造函数不能是虚函数虚表的创建和 vptr 的初始化是在构造函数执行期间完成的。如果构造函数是虚的此时 vptr 尚未就绪无法通过虚表调用自身。析构函数建议设为虚函数重要性当你通过基类指针删除派生类对象时如Base* p new Derive(); delete p;如果析构函数不是虚的只会调用基类的析构函数导致派生类特有的资源无法释放引发内存泄漏。虚函数表存储位置虚表vtable通常存储在可执行文件的只读数据段.rodata。虚表指针vptr随对象存储在堆或栈上。纯虚函数与抽象类声明形式virtual void func() 0;。包含纯虚函数的类称为抽象类不能实例化。5. 性能影响调用开销虚函数调用比普通函数多了一次指针间接寻址的开销vptr $\rightarrow$ vtable $\rightarrow$ func_addr。内联失效由于虚函数是在运行期决定的编译器通常无法在编译期对其进行inline内联优化除非编译器能明确推断出对象类型。缓存影响频繁的虚函数调用可能导致 CPU 指令缓存命中率降低