C++: calling a member function pointer

This article is about calling a member function (method) through a “function pointer”. I decided to write about it because it tricked me for a while, and I think this may be useful to others.

I will start with a small introduction and gradually get to the point. If you’re really in a hurry scroll down to the end of the article to see how it’s done!

Calling a “global” function pointer

In good old C, the following code is probably familiar to most seasoned programmers:

#include <stdio.h>

void func1( void (*func)() ) {
func();
}

void func2() {
printf("Goodbye world!n");
}

int main() {
func1(func2);
}

Now if we compile this and execute it we’ll get of course the following output:

giannis@goofy:~$ gcc fpointer.c
giannis@goofy:~$ ./a.out
Goodbye world!

The slightly strange syntax void (*func)() in func1()’s declaration, is what we call a “pointer to a function”. This one specifically declares that “func is pointer to a function with no arguments and no return value”.

Similarly, void (*func)(int) declares a pointer to a function that takes one int argument and returns no value, and int (*func)() declares a pointer to a function that takes no arguments and returns int.

Function pointers are like data pointers, except the point to executable code instead of data. It is pretty much a standard way in C to encapsulate and delegate behaviors or logic.

Now, let’s take the same scenario only this time within the scope of a C++ class. Consider this:

#include <stdio.h>

class MyClass {

private:

void func1( void (*func)() ) {
func();
}

void func2() {
printf("Goodbye world!n");
}

public:

void method() {
func1(func2);
}
};

int main() {
MyClass myObject;
myObject.method();
}

At least for me, this made sense… But what happens if we try to compile?

giannis@goofy:~$ g++ fpointer.cpp
fpointer.cpp: In member function void MyClass::method():
fpointer.cpp:19: error: no matching function for call to MyClass::func1()
fpointer.cpp:8: note: candidates are: void MyClass::func1(void (*)())

What the error message says, more or less, is that that func1() expected to be called with an argument of type void (*)(), however we tried to pass an “unresolved overloaded function type”.

Okay, that’s weird. func1() expects an argument of type void (*)(), and func2 was exactly of that type, right?

Well, not exactly. func2 is actually a MyClass::void (*)(), that is, it belongs to the MyClass namespace. On the other hand, func1() was expecting a void (*)(), which is a pointer to a function in the global scope/namespace (a “stray” function).

To fix this, we need to need to slightly modify the code in several few places.

First of all, the declaration of func1(). As we said the function will be called with an argument of type MyClass::void (*)(). Therefore it has to be altered accordingly:

void func1( void (MyClass::*func)() ) {
func();
}

Furthermore we need to change the way the function pointer is dereferenced inside func1(). It is not enough to just call func(). Remember that all the compiler knows is the address of a method, which remains the same for all instances of a class. When dereferencing a member function pointer, we also need to provide the object for whom the method is being called, in that case this holds a reference to this object, which is the one we aimed for. Thus, the func1()’s code becomes now:

void func1( void (MyClass::*func)() ) {
(*this.*func)();
}

The (*this.*func)(); statement just instructs the compiler to call the code of MyClass pointed by func, for this object.

And we’re almost done, we need to make one final small change, in the code that passes the member function pointer, so it makes clear that func2 is a method of MyClass and not a “stray” global function:

void method() {
func1(&MyClass::func2);
}

Now it should compile and work as expected:

giannis@goofy:~$ g++ fpointer.cpp
giannis@goofy:~$ ./a.out
Goodbye world!

Let’s put it all together:

#include <stdio.h>

class MyClass {

private:

void func1( void (MyClass::*func)() ) {
(*this.*func)();
}

void func2() {
printf("Goodbye world!n");
}

public:

void method() {
func1(&MyClass::func2);
}
};

int main() {
MyClass myObject;
myObject.method();
}

I hope this helped :-)

This entry was posted in Uncategorized. Bookmark the permalink.

4 Responses to C++: calling a member function pointer

  1. Steve says:

    Wow! This saved me! What a convoluted way of getting it to work. I still don’t understand it but I used it and it worked like a charm. I will study this syntax more closely and try to understand why it works. Thank you so much!

  2. Steve Duff says:

    Excellent! Thanks much for this: it’s as clear an explanation as is possible, and it saved me a ton of experimentation.

    The short story is really basic semantics: the first (“obvious”) way couldn’t ever be accepted by the compiler simply because a class function expects to have a class context to work in; a “this”. The rest pretty much flows from that.

    I would say the error message could be a little less obtuse IMO. Something more like “class function expected” instead of “unresolved overloaded function type”.

  3. Anna says:

    Best explanation possible. I was forgetting the & and all of today I was struggling with this. If only I’d found your article sooner! Now it all makes sense!

  4. Niccola says:

    Fantastic explanation. I was struggling with this for hours. Thank you so much for your time to write down this example!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>