C++多继承中虚表为何存非虚thunk指针而非直接方法指针?
Great question! Let's break this down with practical compiler behavior and memory layout in mind.
First, What's a "Non-Virtual Thunk"?
That 0x400918 0x400820 non-virtual thunk to Child::FatherFoo() entry is a tiny, compiler-generated wrapper function. Its only job is to adjust the this pointer before jumping to the actual inherited implementation of Father::FatherFoo().
Why Do We Need This Thunk?
The core issue here is memory layout in inheritance—specifically when a base class subobject isn't at offset 0 of the derived class object (this is most common in multiple inheritance scenarios).
Let's say Child inherits from two base classes: AnotherBase and Father. The memory layout of a Child object might look like this:
[AnotherBase subobject] → [Father subobject] → [Child's own members]
When you call FatherFoo() via a Child* pointer, the this pointer passed initially points to the start of the entire Child object. But Father::FatherFoo() expects this to point directly to the Father subobject (since that's where Father's member variables are stored).
If the vtable directly pointed to Father::FatherFoo(), the function would use the wrong this pointer—accessing Father members would read/write memory at incorrect offsets, leading to bugs or crashes.
The thunk fixes this: it takes the Child* this pointer, adds the offset to the Father subobject within Child, then calls the real Father::FatherFoo() with the corrected this pointer.
Why Isn't the Child's Vtable Fully Separated from Father's?
The Child vtable is distinct from Father's, but inherited virtual functions need special handling when this pointer adjustment is required. Instead of duplicating the Father::FatherFoo() code (which would be inefficient), the compiler uses a thunk to adapt the this pointer and reuse the existing function implementation.
This approach keeps code lean while ensuring correct behavior for inherited virtual functions in non-trivial inheritance scenarios.
内容的提问来源于stack exchange,提问作者Łukasz Ciałoń




