Another explanation can be that it's a single function pointer, but not directly to the member function.
This doesn't appear to be the case in release builds on VC.net. Based on the following -
Code:
class a
{
public:
void fun()
{
//
}
};
typedef void (a::*amemfun)();
int main()
{
a ins;
amemfun e = a::fun;
(ins.*e)();
return 0;
}
The relevant call in main is -
Code:
00401006 mov dword ptr [ebp-4],offset a::fun (401020h)
0040100D lea ecx,[ebp-5]
00401010 call dword ptr [ebp-4]
The member function begins at 401020h -
Code:
?fun@a@@QAEXXZ:
00401020 push ebp
So it's not a jump into a table.
Altering fun to a virtual function produces the code -
Code:
0040100E mov dword ptr [ebp-4],offset `vcall' (401060h)
00401015 lea ecx,[ebp-8]
00401018 call dword ptr [ebp-4]
at 401060h is (the virtual table) -
Code:
??_9@$BA@AE:
00401060 mov eax,dword ptr [ecx]
00401062 jmp dword ptr [eax]
which then jumps to the correct function.
So based on this it would appear that it is determined at compile time whether the function pointer is to be used on non virtual functions on VC.net.