Pointers to virtual functions with adjustors


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.

Consider:

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
 ret

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 (8)
  1. jj says:

    Surely you mean "May make your head a-splode"

  2. asdf says:

    The pointer can be larger than that depending on the compiler options used (see http://www.codeproject.com/cpp/FastDelegate.asp for a good discussion). Also, the only way to get the address of a member is &Class3::g. The other ways Class3::g and &(Class3::g) are explicitly not allowed in the C++ standard.

  3. Jack Mathews says:

    asdf:

    I knew about Class3::g being illegal but I’d never thought about trying &(Class3::g) with the parenthesis like that. Why is that illegal? Is it something with Class3::g not being a proper reference on its own or something?

  4. Norman Diamond says:

    How come my keyboard’s asdf keys are still working and it’s the jkl; keys that got barfed on? Not fair!

    Sure asdf, I know it’s not your fault, but you should have warned us not to look at that link after eating.

    Hmm. Anyone need a slightly used copy of INCITS+ISO+IEC+14882-2003.pdf for a nice low cheap price?

  5. Raymond Chen says:

    That was adjustor *thunks*, which are related to but not the same as pointer-to-member-function adjustors.

  6. Timur Safin says:

    Err. May be I missed something but I believe this ANSI document should be a good substitute for ISO 14882:2003

    http://webstore.ansi.org/ansidocstore/product.asp?sku=INCITS%2FISO%2FIEC+14882-2003

    And it is only $18 for PDF.

Comments are closed.