C++代码虚表查询次数分析:this指针与虚函数调用的疑问
#include <iostream> class Base { public: virtual void Interface() = 0; virtual ~Base() {}; protected: int Identify() { return SubclassesMustImplement(); } private: virtual int SubclassesMustImplement() = 0; }; class Derived : public Base { public: void Interface() override { std::cout << Identify() << std::endl; }; private: int SubclassesMustImplement() final { return 42; }; }; int main() { Derived d; Base* b = &d; b->Interface(); }
虚表查询次数分析
忽略编译器优化的前提下,这段代码会发生两次虚表查询,具体分析如下:
关于this指针的指向
this指针始终指向实际创建的Derived对象——Base* b = &d只是用基类指针引用派生类对象,对象本身的动态类型还是Derived,不存在“指向Base对象”的情况。
逐步骤拆解虚表查询
第一次查询:
b->Interface()Interface是虚函数,基类指针调用虚函数时必须通过虚表查询,找到Derived::Interface的函数地址,这是第一次虚表查询。第二次查询:
Base::Identify()中调用SubclassesMustImplement()Identify()是非虚函数,编译阶段就能确定调用Base::Identify(),这里不需要虚表查询。- 但
SubclassesMustImplement()是纯虚函数,尽管Derived中用final标记了重写版本,在忽略优化的情况下,标准要求虚函数调用必须通过虚表查询(final只是禁止进一步派生,不强制跳过虚表),因此这里会触发第二次虚表查询,找到Derived::SubclassesMustImplement()的地址。
优化场景补充
如果编译器开启了优化(比如-O2),第二次虚表查询可能被优化掉:因为final标记让编译器可以确定Derived是该函数的最终实现类,直接静态绑定到Derived::SubclassesMustImplement(),无需查询虚表。但题目要求忽略优化,所以按两次查询计算。
内容的提问来源于stack exchange,提问作者segfault
相关产品推荐
相关产品推荐

