You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS2017下通过虚表获取的虚函数指针与&取址结果不一致原因问询

问题原因解释

你观察到的地址差异是Visual Studio使用的MSVC编译器对虚成员函数指针的特有实现导致的,两个指针指向的是完全不同的目标:

  • 你从虚表中直接读取的derivedFuncPtr:是Derived::func函数实现代码的实际内存入口地址,执行这个地址的指令会直接运行你写的打印Derived func的逻辑。
  • 你用&Derived::func拿到的funcDerived:不是函数本身的入口,是MSVC为虚成员函数生成的thunk跳板函数的入口地址。

thunk跳板的作用

MSVC设计thunk的核心目的是兼容成员函数指针的多态调用规则:
成员函数调用需要隐式传递this指针,而虚函数要支持不管用基类还是派生类实例调用都能触发正确的多态逻辑,thunk的逻辑非常简单:

  1. 调整传入的this指针到正确的偏移(多继承场景下这个偏移值不为0,单继承场景下偏移为0也会保留thunk实现)
  2. 直接跳转到虚表中存储的对应实际函数入口执行

你测试中两个地址的差值刚好是这个thunk的代码长度,单继承场景下thunk只有几条简单的跳转指令,长度很小,正好对应你看到的地址差。

为什么调用结果一致

两种调用方式最终都会执行到Derived::func的实际实现代码:

  • 直接调用虚表取出的函数地址,相当于跳过thunk直接执行函数本体
  • 用成员函数指针调用,是先执行thunk的跳转逻辑,再落到函数本体执行
    两者的最终执行逻辑没有区别,所以输出结果完全相同。

注:这个差异是编译器实现细节,C++标准没有对成员函数指针的内存布局、存储内容做强制规定,不同编译器的实现逻辑会有区别,比如GCC下的虚成员函数指针实现就和MSVC不同,测试结果也会不一样。


内容的提问来源于stack exchange,提问作者Lame Programmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:18:05