C ++, equivalence between function pointers and pointer functions?

I'm used to thinking of member functions as a simple case of normal functions, where member functions have an additional parameter at the beginning of their parameter list for the 'this' pointer, that is, the object on which the member function should act. I used boost :: function in the past and have never encountered any problems:

boost::function f<(void)(MyObject*, int, int)> = &MyObject::method_that_takes_two_ints; 

But I saw this syntax for pointers to member functions:

 void (MyObject::*f)( int, int ) = &MyObject::method_that_takes_two_ints; 

In this syntax, the 'this' parameter is not displayed. Which made me wonder if the "pointer to member" functions are really a separate beast under the hood, and this push took care of the details for me.

What defines the standard about the placement of the 'this' parameter? Perhaps only on my compiler does the first argument of 'this' come, and maybe on other compilers it may be at the end? I was just lucky that my way of thinking is consistent with how my compilers handle it (GCC4, VS2005)? Are pointer-member functions always just a special case of a pointer to functions with an additional parameter, or can the compiler implement them differently?

+4
source share
9 answers

The standard says almost nothing about where the this pointer should be located, and in fact, it is quite common to use a different calling convention for member functions. (Thus, the 'this' pointer is not just an optional first argument, it is actually stored in a different place than the first arg usually has)

In particular, MSVC uses the thiscall calling thiscall for member functions and stdcall elsewhere. http://www.hackcraft.net/cpp/MSCallingConventions/#thiscall describes the differences between them, but note that thiscall stores the this pointer in the ECX register, and stdcall stores all the parameters on the stack.

You are definitely better off treating them as completely different types. A pointer to a member function is not just a pointer to a function with an additional parameter.

+10
source

The this pointer is not stored along the pointer to the element (special member pointers are a special case of this). If you just do

 void (MyObject::*f)( int, int ) = &MyObject::method_that_takes_two_ints; 

what is stored is simply the information that the member function must call on the object that you must later provide. If you want to call it, you need to pass an object where the compiler gets the this pointer.

 MyObject o; (o.*f)(1, 2); 

A member function pointer is only a member pointer whose type (which indicated) is a type of function. The standard states that member function pointers do not have their own β€œmember function type” that they point to, and which will somehow include this type of pointer.

 int main() { typedef void fun() const; fun MyObject::*mem_function_ptr = &MyObject::const_method_that_takes_two_ints; } 

fun in this code is a function type. A type that has a "normal" function. A pointer to a function, unlike a pointer to a member function, is simply a pointer to a function of this type:

 void foo() { cout << "hello"; } int main() { typedef void fun(); fun * f = &foo; } 

Whereas a pointer-member-function has an extra level-pointer at the top of this type of function.

Something about the this pointer and how it relates to the object it points to (not technical, but only theoretical material):

Each member function has a hidden parameter called an implicit object parameter , which is of type MyObject& or MyObject const& , depending on whether you have a const or nonconst function. The object on which you call the member function, o , is the implied object argument , which is passed to the parameter. In standard theory, which make up the rules that describe how member functions are called, the implicit object parameter is the first hidden parameter. This is conceptual and does not mean that this is a real case in implementation. Then, the implied argument of the object is bound to this implicit parameter of the object, which can lead to implicit conversions (therefore, if you call the const member function for an object that is not a constant, the qualification transformation is converted from MyObject to MyObject const& . Non-const function selects better, than const functions for calling, for a non-constant object). For example, in this code you can say:

 struct A { operator int() const { return 0; } }; int main() { A a; int i = a; // implicit conversion using the conversion function } 

That the implied argument of an object a type a bound to an implicit parameter of an object of type A const& , the object of which is pointed to by a pointer of this type A const* here. It is important to note that the parameter of an implicit object is only a theoretical construction in order to formalize how the rules are compiled for calling a member function (and the constructors do not include them), while this pointer actually exists. this is a pointer, because when this was introduced, C ++ has no references so far.

I hope this helps you figure it out.

+9
source

A great article on member function pointers is CodeProject Member function pointers and the fastest C ++ delegates . This article describes pointers to member functions from simple cases using function pointers to virtual member functions with multiple inheritance. As a bonus, it provides the implementation of delegates that can be really useful.

+7
source

Yes, function pointers and element pointers are completely different animals. Pointers to members must have an instance of the object to be dereferenced using the operators ->* or .* . The this parameter is used when creating a pointer to an element, since this is determined when a pointer to an element is used (the object to the left of ->* or .* ).

Note that there is probably less difference between the member pointer function and the member pointer variable than between the member pointer function and the regular function pointer.

Usually, member functions and regular functions can have completely different calling conventions, so you cannot distinguish between them.

+3
source

Note that the size of the member pointer function may vary for different compilers.

Another note written in The Old New Thing blog :

The size of a member-pointer function may vary depending on the class.

+3
source

They are definitely different types, and any assumptions you make will be platform / compiler specific.

This page contains more information about the implementation of member function points than I ever wanted to know, including implementation details for many popular compilers.

+1
source

To answer all questions: Yes, they are special pointers other than regular pointers. Yes, boost :: function recognizes them.

The standard does not say anything about the internal details of call stacks. In fact, many compilers can use integer registers, floating point registers, and / or the stack, depending on the actual argument list. The 'this' pointer is another special case.

The Boost :: function resolves this with two code codes inside. You can see this by checking the call stack for two cases. If your boost :: function stores a pointer to a member function, the () operator will split the argument list. The first argument is used as the object from which the member function is called with the remaining arguments.

+1
source

To complement everyone else, Boost.Function works by specializing in an assignment operator on member function pointers so that it can detect when you passed it. When you call this function, it internally reinterprets it with the correct method of calling the member function pointer ( (obj->*fun)(args) ).

0
source

I think you can find this link quite interesting:

http://www.parashift.com/c++-faq-lite/pointers-to-members.html

This is a very good description of everything you want to know about member pointers.

0
source

All Articles