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

通过vptr调用C++虚函数:如何调用第二个虚函数?

Understanding vptr, VTABLE, and Calling Virtual Functions Manually

Hey there! Let's break down your code and question step by step so you grasp exactly how that pointer manipulation works, and how to call the second virtual function.

First: What's happening in your existing code?

Your line void(*firstfunc)() = (void(*)(void))(*(int*)*(int*)p); is manually traversing the virtual function table (VTABLE) via the virtual pointer (vptr). Here's a play-by-play:

  1. p is a base* pointing to a derived object. For classes with virtual functions, the first piece of memory in the object is the vptr—a pointer to the class's VTABLE.
  2. (int*)p: Cast the object pointer to int* so we can read the first 4 bytes (assuming 32-bit architecture; for 64-bit, you'd use long long* or uintptr_t to match pointer size) which holds the vptr address.
  3. *(int*)p: Dereference this to get the actual value of the vptr—this is the starting address of the derived class's VTABLE.
  4. (int*)*(int*)p: Cast the VTABLE address to int* so we can index into the array of function pointers stored in the VTABLE.
  5. *(int*)*(int*)p: Dereference this to get the first function pointer in the VTABLE.
  6. (void(*)(void)): Cast that raw address to a function pointer type that matches the signature of your virtual functions (no parameters, no return value).
  7. Calling firstfunc() runs that first virtual function, which is derived::fun_2()—because the VTABLE order follows the order of virtual function declarations in the base class: fun_2 is first, then fun_3, then fun_4.

How to call the second virtual function?

To call the second virtual function (fun_3), you just need to access the second element in the VTABLE array. That means adding an offset of 1 to the VTABLE pointer (since each element is a function pointer).

Here's the modified code for the second function:

int main() {
    base *p;
    derived obj1;
    p = &obj1;
    
    // Call first virtual function (fun_2)
    void(*firstfunc)() = (void(*)(void))(*(int*)*(int*)p);
    firstfunc();
    
    // Call second virtual function (fun_3)
    void(*secondfunc)() = (void(*)(void))(*((int*)*(int*)p + 1));
    secondfunc();
}

When you run this, the output will be:

derived-2
base-3

Because derived doesn't override fun_3, so the VTABLE uses the base class's implementation.

Important Notes

  • This is undefined behavior according to the C++ standard. The standard doesn't specify how virtual functions are implemented—compilers can use different VTABLE layouts, add extra data, or even omit vptr/VTABLE entirely in some cases (like when a class has no virtual functions or is optimized).
  • The code assumes 32-bit pointers (using int*). For 64-bit systems, replace int* with long long* or uintptr_t (from <cstdint>) to avoid pointer truncation.
  • This is purely for learning purposes! Never write code like this in production—use normal virtual function calls (p->fun_3()) instead, which are safe, readable, and compiler-friendly.

内容的提问来源于stack exchange,提问作者Blood-HaZaRd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:23:32