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.
}

Comments (1)
  1. Alex Harford says:

    One thing that gave me trouble was using pointers to functions that are member functions of the same object, ie; pMemFunc is also a member of MyObj.

    The following syntax is required:

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

    According to Fruny from the page below, "Unlike regular functions, member function names do not implicitely decay to function pointers."

    I found the solution here:

    http://www.gamedev.net/community/forums/topic.asp?topic_id=177565

    Hope this can help some others.

Comments are closed.

Skip to main content