Pointers to virtual functions with adjustors

Raymond Chen


As a mental exercise, let’s combine two mind-numbing facts about pointers to member functions, namely that all pointers to virtual functions look the same and that pointers to member functions are very strange animals. The result may make your head explode.


class Class1 {
 public: virtual int f() { return 1; }
class Class2 {
 public: virtual int g() { return 2; }
class Class3 : public Class1, public Class2 {
int (Class3::*pfn)() = Class3::g;

Here, the variable pfn consists of a code pointer and an adjustor. The code pointer gives you the virtual call stub:

 mov eax, [ecx]             ; first vtable
 jmp dword ptr [eax]        ; first function

and the adjustor is sizeof(Class1) (which in our case would be 4 on a 32-bit machine). The result, then, of compiling a function call (p->*pfn)() might look something like this:

 mov ecx, p
 lea eax, pfn
 add ecx, dword ptr [eax+4] ; adjust
 call dword ptr [eax]       ; call
-- transfers to
 mov eax, [ecx]             ; first vtable
 jmp dword ptr [eax]        ; first function
-- transfers to
 mov eax, 2                 ; return 2

Okay, I lied. It’s really not all that complicated after all. But you can probably still impress your friends with this knowledge. (If you have really geeky friends.)


Comments are closed. Login to edit/delete your existing comments