ROTOGG
ROTOGG

Reputation: 1136

Value of Pointer to Non-Static Member function

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 member 0x4

Foo::foo pointer to function member 0x804844c

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.

  1. It cannot be a simple offsetOf(), as this is a big offset.
  2. It cannot be the address of vtbl (or address of an entry in vtbl) because I believe vbtl is an entity associated with instantiated object, not with the class.
  3. It cannot be the address where the function's implementation code is loaded. Because the same pointer can behave polymorphically when applied with a derived object.

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

Answers (1)

Kaz
Kaz

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

Related Questions