Function Pointers to Non-Static Object Methods

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

One of the first things that I noticed when learning C++, was that function pointers had become much more difficult to use with object architecture. Each function/method needs to know what object it is part of.  So, to point to an object's method, we also must know about an object. Using the data from each, we can freely call any method of any object, without knowing exactly what we are calling.

The code I have included is a holder class that takes a pointer to an object and a pointer to a method.  Either can be changed at any time. During the lifetime of the holder class object, a helper method can be called that calls the stored method pointer.   Its that simple...Sort-of.  The syntax can get a little confusing, but I'll try to walk you through.

First, an abstract base class is defined.  The CMethodPtr class is derived from this class, but this class is used to pass the data around between functions. You'll see what I mean later.

// R is the return type
template <class R>
class CMethodPtrBase
    virtual R CallMethod() = 0;
    virtual R CallMethod(LPVOID arg1) = 0;
    virtual R CallMethod(LPVOID arg1, LPVOID arg2) = 0;

Next is the derived class.  Both the abstract base class and the derived class require the return type of the function being held.  The derived class requires another template argument declaring the type of object this holder will store. Neither of these can be changed once the holder has been declared.

The constructor takes a pointer to the actual object( not the definition like above) that contains the method we will call. It also takes a pointer to the method.  The METHOD macro is used to easily pass the method into the holder.

The CallMethod() methods are the helper methods for calling the method that the holder object contains.  The different versions are for different numbers of arguments.   If more arguments are needed, then add new functions to the abstract base class and to this class.

// r = return type
// o = object definition
// m = method
#define METHOD(r,o,m) (r (o::*)() )(&o::m)

// O = object definition
// R = return type
template <class O, class R>
class CMethodPtr : public CMethodPtrBase<R>
    typedef R (O::*PMETHOD)();
    typedef R (O::*PMETHOD1)(LPVOID);
    typedef R (O::*PMETHOD2)(LPVOID, LPVOID);

    CMethodPtr(O* pObject, PMETHOD pMethod) : m_pObject( pObject ), m_pMethod( pMethod ) {};

    // Member Variables
    O*    m_pObject;    // pointer to an object
    PMETHOD    m_pMethod;    // pointer to the method

    void SetObject( O* pObject ) { m_pObject = pObject; }
    void SetMethod( PMETHOD pMethod ) { m_pMethod = pMethod; }

    // 0 args
    virtual R CallMethod()
        return (m_pObject->*m_pMethod)();

    // 1 arg
    virtual R CallMethod(LPVOID arg1)
        return (m_pObject->*(PMETHOD1)m_pMethod)(arg1);

    // 2 args
    virtual R CallMethod(LPVOID arg1, LPVOID arg2)
        return (m_pObject->*(PMETHOD2)m_pMethod)(arg1, arg2);

That is basically it for the definition.  Here is how it is used:

Somewhere declare the object that has the method we want to point to and the holder object:

// A helper macro that uses the METHOD macro
#define SUMMETHOD(m) METHOD(int, CSumObject, m)

CSumObject m_SumObject;   // The object that has the method we want to point to
CMethodPtr<CSumObject, int> m_SumMethodPtr( &m_SumObject, SUMMETHOD(Function2) ); // Uses a CSumObject thats returns an int

Function2() is the method that will be held. Later on we can call that function like this:

int nArg1 = 5;
int nArg2 = 10;

int nReturn;

nReturn = m_SumMethod.CallMethod( &nArg1, &nArg2 );  // Whatever it was pointing to, we just called it

If you want to pass a holder object through a function, define the function this way:

int MyObject::SomeFunction( CMethodPtrBase<int> pMethodPtr )
    return pMethodPtr->CallMethod();

Notice the abstract base class is used so that we do not have to know what type of class the CMethodPtr object is holding.  If we used CMethodPtr directly, the template arguments would require us to tell it what type of class the CMethodPtr object was holding.

Take a look at the demo project or source to see a more thorough example.

Download demo project - 15.8 KB

Download source - 7.7 KB


  • Whats the LONG way around doing that.

    Posted by Legacy on 11/29/2000 12:00am

    Originally posted by: aaron Yemm

    I need to do exactly that for one of my projects. But i have made sure that the pointer to the function knows what object it belongs to just by putting the (ClassName::*pFunc) in wherever it was required.
    now when i try to invoke the function in the view as in pDoc->pFunc(params); it states that the expression does not evaluate to a function. I have made a function which gets a pFunc passed to it so that i dont have to directly call the pointer function in the view. But i get the same error. It should work either way I suppose. I know I dont need the function which has a pFunc passed to it. But i thought it may fix it. Have a quick fix?


  • how would you approach callback functions?

    Posted by Legacy on 02/14/1999 12:00am

    Originally posted by: Joe Shapiro

    I've often wondered how I might pass a call back function pointer to qsort, for example, that is actually a non-static member function.

    Do you have any thoughts on this topic?

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Download this IDC report to learn how your organization can benefit from new flash architecture built for the cloud era. The IDC report examines the evolving primary flash array market with a particular emphasis on how next generation flash–driven enterprise storage architectures will take performance, scalability and infrastructure density to the next level.

  • Learn which Mobile Development Platforms scored the highest in the current Forrester Wave. This report details the research findings about how well vendors fulfilled the 32 criteria to help you select the right partner for your mobile development platform needs. Download a free copy of the report compliments of Kinvey, a Progress company.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date