Member function pointers
In the C# era we are living, it’s more and more important to have efficient notifications callbacks in C++. We have standard C callbacks notifications, and member function pointers.
They are usually declared as typedef void (CMyClass::*MyTypeDefName)(Parameters);and called with (pMyClass->*)m_MyCallback(params);
I used in a project it to have a simple template signal class. Today, we came across a bug : an object’s constructor was not initializing properly, filling wrong members with wrong values. It seemed he did’nt knew the right offsets for its own class ! Interesting thing, this object contained member function pointers…
Visual C++ weird implementation
The answer was “In Visual C++, member function pointers have different sizes, depending on what compiler knows about the target class”. As explained in this thread (2nd post) the member function pointers can vary from 4 bytes to 16 bytes.
16 bytes is for classes that are forward declared even if you fully declare them after ! See example below:
Case 1
class CForward {}; // full declaration only typedef void (CForward::*FnType)(int); // sizeof(FnType) == 4
Case 2
class CForward; // forward declaration typedef void (CForward::*FnType)(int); // sizeof(FnType) == 16
Case 3
class CForward; // forward declaration class CForward {}; // full declaration typedef void (CForward::*FnType)(int); // sizeof(FnType) == 16
So, if you forward declare a class, and include this class header, any function pointer to this class will be 16 bytes. If you only include the header, pointer will vary from 4 to 12 bytes (depending on the class).
As said in the thread, the simplest solution is to use VC++ #pragma directive, included everywhere in your code (MSDN link here)
// will force all pointers to 16 bytes #pragma pointers_to_members(full_generality, virtual_inheritance) // will force all pointers to 8 bytes, use if you don't have // virtual inheritance (general case) #pragma pointers_to_members(full_generality, multiple_inheritance) // will force all pointers to 4 bytes, use if you don't have // multiple inheritance #pragma pointers_to_members(full_generality, single_inheritance)
In strongly encourage you to use one of these methods (or to use /vmg compiler switch), to be sure all the function pointers of your code have the same size !
Don’t be afraid of using a restrictive pragma directive, VC++ throws an error message if you use too restrictive pointers: error C2287: inheritance representation: ’single_inheritance’ is less general than the required ‘multiple_inheritance’