Reputation: 1136
I am trying to understand the underlying mechanism used to realize pointer to non-static member function. I am looking for an answer similar to how vtbl (virtual table for polymophism) works in the big picture, without worrying the details that could be different from compiler to compiler.
Example:
#include <stdio.h>
class A {
public:
int i;
int j;
void foo(void) { };
};
int main ()
{
int A::*ptr_j = &A::j;
void (A::*ptr_f)(void) = &A::foo;
printf("Foo::j pointer to data member %p\r\n", ptr_j);
printf("Foo::foo pointer to function member %p\r\n", ptr_f);
}
The result is
Foo::j
pointer to data member0x4
Foo::foo
pointer to function member0x804844c
From "The C++ Programming Language By Stroustrup",
A pointer to member...is more like an offset into a structure or an index into an array...
For a data member, I understand that Pointer-To-Member Foo::j
is more or less equivalent to offsetOf(Foo, j)
. The value when using gcc compiler in my host environment is 4, and it matches that offsetOf(Foo, j)
is 4.
For a function member, the returned value is 0x804844c
. And this is some address that belongs to global data area (where class is loaded?)
So my question is:
What is the "object" that is address 0x804844c
.
offsetOf()
, as this is a big offset.Then what is the object at address 0x804844c
, and what is its role in translating the pointer-to-member-function into the actual function address when operator ->*
or .*
is applied?
Upvotes: 2
Views: 209
Reputation: 58588
You cannot print the values of pointer-to-member objects using the %p
conversion specifier of printf
. They are not necessarily regular pointers. The %p
specifier requires a void *
value. Strictly speaking, you cannot even portably print a regular function pointer with %p
, because this requires a conversion of a function pointer to void *
.
Pointer-to-member types do not necessarily fit into one machine word that can hold an address. They can be data structures with several fields.
I believe vbtl is an entity associated with instantiated object, not with the class.
This is incorrect. Virtual tables are static structures, and instances only point to them. All instances of a given class share a pointer to the same table.
A pointer to a non-static member function is simpler in one regard in that it doesn't have to deal with the offset of an arbitrary data member in a class instance. However, a pointer to a non-static member function is complicated by the need to support virtual functions, and by the fact that code which calls through a pointer like this doesn't know or care whether it's calling a virtual or non-virtual function.
One implementation strategy for pointers to member functions involves thunks: pieces of compiler-generated code which perform the right kind of logic to do the call in the right way. A pointer to member can then point at the thunk. The thunk knows where in the this
object to find the vtable pointer, and which offset in the vtable is the function that is ultimately to be called.
Upvotes: 3