Using C++ Member Function Pointers

I don't know about you, but the C++ syntax for member function pointers always eludes me.  Every time I would spend half an hour or more deciphering MSDN to get the exact syntax, only to completely forget it the next time.  Oops.

 

I can think of three reasons why this is happening:

 

  1. The C++ syntax sucks;
  2. I'm getting old; and
  3. The existing documentation sucks.

 

While I cannot do much about the first two, I figure at least I can work on the third.  The result is this quick reference.  It has helped me in a number of situations.  It might help you as well, if you are getting old too!

 

You use a member function pointer because eventually you want to invoke it.  Before you can do that, you also need to declare the type of the pointer, define a variable of that type, and assign a value to that variable.  This reference teaches you how to do each of them.

 

  • Declaring a member function pointer type

 

Suppose you want to point to a non-static member function of a class CMyClass, where the argument has type Arg and the result type is Res. You can declare the type of your pointer by

 

typedef Res (CMyClass::*MemFunc)( Arg );

 

(Note the highlighted parentheses cannot be omitted).

 

Then you can declare your member function pointer pMemFunc as having type MemFunc:

 

MemFunc pMemFunc;

 

  • Obtaining a value of your member function pointer type

 

The next step, you need to give a value to your pointer. Suppose the CMyClass class looks like:

 

class CMyClass

{

...

Res MyMethod( Arg arg );

...

};

 

You can let pMemFunc points to the function MyMethod by:

 

pMemFunc = &CMyClass::MyMethod;

 

Alternatively, you can do without the ampersand, which is my preferred way:

 

pMemFunc = CMyClass::MyMethod;

 

  • Invoking a member function via a member function pointer

 

Now that your pointer has a value, it's time to put it to use! Since pMemFunc points to a member function, you need to have an object to begin with. Suppose the object is called MyObj:

 

CMyClass MyObj;

 

You can invoke the function pointed to by pMemFunc on MyObj like this:

 

Res result = (MyObj.*pMemFunc)( arg );

 

Note that the highlighted parentheses cannot be omitted.

 

However, none of the following syntaxes is accepted:

 

Res result = MyObj.(*pMemFunc)( arg );

// Won't compile

Res result = MyObj.*pMemFunc( arg );

// Won't compile either

Res result = MyObj.pMemFunc( arg );

// You wish!

 

This is different from how C++ treats member functions (you can write either (MyObj.MyMethod)( arg ) or MyObj.MyMethod( arg )), and different from how it treats ordinary (non-member) function pointers too (given a function pointer pFunc, you can invoke it with either (*pFunc)( arg ) or pFunc( arg )).

 

In an ideal language, all constructs should be equal (to be precise, I mean "orthogonal").  Now C++ is telling me that member function pointers are less equal than others.  This bothers me.  This bothers me tremendously.

 

Maybe C++ has become old?

 

P.S. Someone who calls himself “Daniel” made the following comment:

Bjarne Stroustrup said, "I consider the C declarator syntax an experiment that failed." But we're stuck with it. If you read 'The Design and Evolution of C++' a much nicer syntax is suggested.  Sort of reminiscent of Pascal I think.

I haven't got a reference to hand, but I think you need the brackets for calling member functions because otherwise it could mean that you were calling a function which return a pointer to a member variable. ie. MyObj.*pMemFunc( arg ) is equivalent to MyObj.*(pMemFunc( arg )). Here's some code to illustrate:

#include <iostream>

struct my_object
{
    int x;
};

int my_object::* function()
{
    return &my_object::x;
}

int main()
{
    my_object x = {1};
    x.*function() = 3;
    std::cout<<x.x<<'\n'; // Prints 3.
}