通过子类对象直接调用虚方法是否永远不会使用vtable?
问题分析与解答
示例代码
#include <iostream> #include <array> struct Base { virtual float getValue() { return 1.0f; } }; struct Derived : Base { float getValue() override { return 2.0f; } }; inline void test(Base *obj) { std::cout << obj->getValue() << std::endl; } int main() { Derived d; test(&d); float value = d.getValue(); std::cout << value << std::endl; }
关于float value = d.getValue();的编译方式
是的,这个调用永远不会通过vtable(虚表),和调用非虚函数的机制本质一致。
原因很明确:这里的d是Derived类型的具体对象实例,不是基类指针或引用。在编译阶段,编译器可以100%确定这个对象的静态类型和动态类型完全一致,不存在多态的可能性——不可能出现d实际是其他派生类对象的情况。因此编译器会直接将调用解析为Derived::getValue(),生成直接函数调用的机器指令,完全不需要在运行时去虚表中查找函数地址。
只有当调用虚函数的是基类指针或引用时,因为其动态类型可能和静态类型不一致(比如基类指针指向派生类对象),编译器无法在编译期确定要调用的函数,这时候才会通过vtable做运行时的函数地址查找。
内容的提问来源于stack exchange,提问作者markzzz
相关产品推荐
相关产品推荐

