153

How do I obtain a function pointer for a class member function, and later call that member function with a specific object? I’d like to write:

class Dog : Animal
{
    Dog ();
    void bark ();
}

…
Dog* pDog = new Dog ();
BarkFunction pBark = &Dog::bark;
(*pBark) (pDog);
…

Also, if possible, I’d like to invoke the constructor via a pointer as well:

NewAnimalFunction pNew = &Dog::Dog;
Animal* pAnimal = (*pNew)();    

Is this possible, and if so, what is the preferred way to do this?

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
Tony the Pony
  • 40,327
  • 71
  • 187
  • 281
  • 10
    Why do you allocate that dog dynamically? You then have to manually delete the object, too. This looks a lot like you're coming from Java, C# or some other comparable language and still fight with C++. A plain automatic object (`Dog dog;`) is more likely what you want. – sbi Sep 28 '09 at 09:18
  • 1
    I still don't really understand 'why' if you want to call a objects member function then simply pass a pointer to the object? If people complain that because it enables you to encapsulate the class better why not make an interface class that all class inherit from? – Chad Sep 28 '09 at 08:39
  • 1
    It can be useful in implementing something like the command pattern although many people would use boost::function to hide the raw member pointer mechanics. – CB Bailey Sep 28 '09 at 08:45
  • Thanks for the comment. Just after so many years of programing I've seen it used all over the place. I just consider passing a object cleaner and simpler. – Chad Sep 28 '09 at 08:56
  • 2
    @Chad: I would mostly agree but there are times where passing a reference would be more costly. Consider a loop that is iterating over some type of data (parsing, calculation, etc..) than being able to call a function based on some if/else calculations imposes a cost where just calling the pointed too function could avoid such if/then/else checks if these checks could be done before entering the loop. – Eric Oct 25 '12 at 18:04
  • Thanks Eric didn't see it that way. – Chad Oct 26 '12 at 05:12
  • 1
    Also see [Function pointer to member function](https://stackoverflow.com/q/2402579/608639). – jww Aug 02 '19 at 04:54
  • Check @CiroSantilli 's answer bellow, other answer are more or less off topic. – jw_ Jan 31 '20 at 03:14
  • Helpful blog post: [The Function Pointer Tutorials](http://www.newty.de/fpt/fpt.html#defi) – Gabriel Staples Feb 23 '22 at 22:50
  • I would do some research on [std::function](https://en.cppreference.com/w/cpp/utility/functional/function) it's worth it. – Tonia Sanzo Apr 30 '22 at 13:19
  • @jww I see what you did there. – JasonN Sep 17 '22 at 02:50

11 Answers11

163

Read this for detail :

// 1 define a function pointer and initialize to NULL

int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL;

// C++

class TMyClass
{
public:
   int DoIt(float a, char b, char c){ cout << "TMyClass::DoIt"<< endl; return a+b+c;};
   int DoMore(float a, char b, char c) const
         { cout << "TMyClass::DoMore" << endl; return a-b+c; };

   /* more of TMyClass */
};
pt2ConstMember = &TMyClass::DoIt; // note: <pt2Member> may also legally point to &DoMore

// Calling Function using Function Pointer

(*this.*pt2ConstMember)(12, 'a', 'b');
Zoe
  • 27,060
  • 21
  • 118
  • 148
Satbir
  • 6,358
  • 6
  • 37
  • 52
  • 32
    Surprising that they decided that this: `*this.*pt2Member` would work. `*` has higher precedence over `.*`... Personally, I would still have written `this->*pt2Member`, that's one less operator. – Alexis Wilke Feb 17 '14 at 03:51
  • 8
    Why do you have to initialize `pt2ConstMember` to `NULL`? – Ciro Santilli OurBigBook.com Jul 01 '15 at 09:00
  • 1
    @AlexisWilke why is it surprising? For direct objects (not pointers) it is `(object.*method_pointer)`, so we want the `*` to have greater priority. – Ciro Santilli OurBigBook.com Jul 01 '15 at 09:02
  • 1
    @TomášZato, if I'm not mistaken (and I might be), `this` is just being used to demonstrate that whatever you apply `.*` to should be a pointer to an instance of the (sub)class. However this is new syntax to me I'm only guessing based on other answers and resources linked here. I'm suggesting an edit to make that more clear. – c1moore Jan 31 '18 at 23:15
  • Why are we calling through `*this`? Is that really necessary? What about `this->*pt2ConstMember)(12, 'a', 'b')`? Wouldn't that work? What about `this->pt2ConstMember)(12, 'a', 'b')`? Wouldn't that work? See the summary of the answer at the end of [my question here](https://stackoverflow.com/q/31869026/4561887). I'm pretty sure the `*` in front of the `pt2ConstMember` function pointer is optional when calling it as a function. – Gabriel Staples Feb 05 '22 at 23:46
  • Also, must we call through a class or subclass (I think the answer is yes), or can we call this method function in a standalone form without an object (I think the answer is no)? – Gabriel Staples Feb 05 '22 at 23:49
68

How do I obtain a function pointer for a class member function, and later call that member function with a specific object?

It's easiest to start with a typedef. For a member function, you add the classname in the type declaration:

typedef void(Dog::*BarkFunction)(void);

Then to invoke the method, you use the ->* operator:

(pDog->*pBark)();

Also, if possible, I’d like to invoke the constructor via a pointer as well. Is this possible, and if so, what is the preferred way to do this?

I don't believe you can work with constructors like this - ctors and dtors are special. The normal way to achieve that sort of thing would be using a factory method, which is basically just a static function that calls the constructor for you. See the code below for an example.

I have modified your code to do basically what you describe. There's some caveats below.

#include <iostream>

class Animal
{
public:

    typedef Animal*(*NewAnimalFunction)(void);

    virtual void makeNoise()
    {
        std::cout << "M00f!" << std::endl;
    }
};

class Dog : public Animal
{
public:

    typedef void(Dog::*BarkFunction)(void);

    typedef Dog*(*NewDogFunction)(void);

    Dog () {}

    static Dog* newDog()
    {
        return new Dog;
    }

    virtual void makeNoise ()
    {
        std::cout << "Woof!" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    // Call member function via method pointer
    Dog* pDog = new Dog ();
    Dog::BarkFunction pBark = &Dog::makeNoise;

    (pDog->*pBark)();

    // Construct instance via factory method
    Dog::NewDogFunction pNew = &Dog::newDog;

    Animal* pAnimal = (*pNew)();

    pAnimal->makeNoise();

    return 0;
}

Now although you can normally use a Dog* in the place of an Animal* thanks to the magic of polymorphism, the type of a function pointer does not follow the lookup rules of class hierarchy. So an Animal method pointer is not compatible with a Dog method pointer, in other words you can't assign a Dog* (*)() to a variable of type Animal* (*)().

The static newDog method is a simple example of a factory, which simply creates and returns new instances. Being a static function, it has a regular typedef (with no class qualifier).

Having answered the above, I do wonder if there's not a better way of achieving what you need. There's a few specific scenarios where you would do this sort of thing, but you might find there's other patterns that work better for your problem. If you describe in more general terms what you are trying to achieve, the hive-mind may prove even more useful!

Related to the above, you will no doubt find the Boost bind library and other related modules very useful.

gavinb
  • 19,278
  • 3
  • 45
  • 60
  • 15
    I have used C++ for over 10 years, and keep learning something new on a regular basis. I'd never heard of `->*` before, but now I hope I'll never need it :) – Thomas Sep 28 '09 at 11:37
  • @Thomas You might never 'need' it, but there are good reasons to use it. For example, it's not uncommon to use arrays of function pointers to implement instruction decoding/dispatching in an emulator, and for a class you'll typically want those function pointers to be member function pointers so they capture all the necessary context. – Pharap Jan 15 '23 at 14:26
38

I don't think anyone has explained here that one issue is that you need "member pointers" rather than normal function pointers.

Member pointers to functions are not simply function pointers. In implementation terms, the compiler cannot use a simple function address because, in general, you don't know the address to call until you know which object to dereference for (think virtual functions). You also need to know the object in order to provide the this implicit parameter, of course.

Having said that you need them, now I'll say that you really need to avoid them. Seriously, member pointers are a pain. It is much more sane to look at object-oriented design patterns that achieve the same goal, or to use a boost::function or whatever as mentioned above - assuming you get to make that choice, that is.

If you are supplying that function pointer to existing code, so you really need a simple function pointer, you should write a function as a static member of the class. A static member function doesn't understand this, so you'll need to pass the object in as an explicit parameter. There was once a not-that-unusual idiom along these lines for working with old C code that needs function pointers

class myclass
{
  public:
    virtual void myrealmethod () = 0;

    static void myfunction (myclass *p);
}

void myclass::myfunction (myclass *p)
{
  p->myrealmethod ();
}

Since myfunction is really just a normal function (scope issues aside), a function pointer can be found in the normal C way.

EDIT - this kind of method is called a "class method" or a "static member function". The main difference from a non-member function is that, if you reference it from outside the class, you must specify the scope using the :: scope resolution operator. For example, to get the function pointer, use &myclass::myfunction and to call it use myclass::myfunction (arg);.

This kind of thing is fairly common when using the old Win32 APIs, which were originally designed for C rather than C++. Of course in that case, the parameter is normally LPARAM or similar rather than a pointer, and some casting is needed.

Ziezi
  • 6,375
  • 3
  • 39
  • 49
  • 'myfunction' is not a normmal function if by normal you mean a C style function. 'myfunction' is more accurately called a method of myclass. Methods of a class are not like normal functions in that they have something a C style function does not which is the 'this' pointer. – Eric Oct 25 '12 at 17:57
  • 3
    advising to use boost is draconian. There are practical good reasons for using method pointers. I don't mind the mention of boost as an alternative but hate when someone says someone else should use it without knowing all the facts. Boost comes at a cost! And if this is an embedded platform then it may not be a choice that's possible. Beyond this, I really like your write up. – Eric Oct 25 '12 at 18:10
  • @Eric - On your second point, I didn't intend to say "thou shalt use Boost", and in fact I've never used Boost myself. The intention (as far as I know it after 3 years) was that people should look for alternatives, and to list a few possibilities. "Or whatever" indicates that a list isn't meant to be exhaustive. Member pointers have a cost in readability. Their concise source representation can also disguise run-time costs - in particular a member pointer to a method must cope with both non-virtual and virtual methods, and must know which. –  Oct 25 '12 at 22:09
  • @Eric - Not only that, but these issues are a reason for non-portability with member pointers - Visual C++, at least in the past, needed some extra clues about how to represent member pointer types. I'd use the static function approach for an embedded system - the representation of a pointer is the same as any other function pointer, the costs are obvious, and there's no portability issue. And the call wrapped by the static member function knows (at compile time) whether the call is virtual or not - no run-time checks needed beyond the usual vtable lookups for virtual methods. –  Oct 25 '12 at 22:15
  • @Eric - on your first point - I'm aware that a static member function isn't exactly the same as a C-style function (hence "scope issues aside"), but I probably should have included the name. –  Oct 25 '12 at 22:23
21
typedef void (Dog::*memfun)();
memfun doSomething = &Dog::bark;
....
(pDog->*doSomething)(); // if pDog is a pointer
// (pDog.*doSomething)(); // if pDog is a reference
Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
  • 2
    Should be: (pDog->*doSomething)(); // if pDog is a pointer // (pDog.*doSomething)(); // if pDog is a reference as () operator has higher priority then ->* and .*. – Tomek Sep 28 '09 at 09:13
19

Minimal runnable example

main.cpp

#include <cassert>

class C {
    public:
        int i;
        C(int i) : i(i) {}
        int m(int j) { return this->i + j; }
};

int main() {
    // Get a method pointer.
    int (C::*p)(int) = &C::m;

    // Create a test object.
    C c(1);
    C *cp = &c;

    // Operator .*
    assert((c.*p)(2) == 3);

    // Operator ->*
    assert((cp->*p)(2) == 3);
}

Compile and run:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

Tested in Ubuntu 18.04.

You cannot change the order of the parenthesis or omit them. The following do not work:

c.*p(2)
c.*(p)(2)

GCC 9.2 would fail with:

main.cpp: In function ‘int main()’:
main.cpp:19:18: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘p (...)’, e.g. ‘(... ->* p) (...)’
   19 |     assert(c.*p(2) == 3);
      |

C++11 standard

.* and ->* are a single operators introduced in C++ for this purpose, and not present in C.

C++11 N3337 standard draft:

  • 2.13 "Operators and punctuators" has a list of all operators, which contains .* and ->*.
  • 5.5 "Pointer-to-member operators" explains what they do
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
16

I came here to learn how to create a function pointer (not a method pointer) from a method but none of the answers here provide a solution. Here is what I came up with:

template <class T> struct MethodHelper;
template <class C, class Ret, class... Args> struct MethodHelper<Ret (C::*)(Args...)> {
    using T = Ret (C::*)(Args...);
    template <T m> static Ret call(C* object, Args... args) {
        return (object->*m)(args...);
    }
};

#define METHOD_FP(m) MethodHelper<decltype(m)>::call<m>

So for your example you would now do:

Dog dog;
using BarkFunction = void (*)(Dog*);
BarkFunction bark = METHOD_FP(&Dog::bark);
(*bark)(&dog); // or simply bark(&dog)

Edit:
Using C++17, there is an even better solution:

template <auto m> struct MethodHelper;
template <class C, class Ret, class... Args, Ret (C::*m)(Args...)> struct MethodHelper<m> {
    static Ret call(C* object, Args... args) {
        return (object->*m)(args...);
    }
};

which can be used directly without the macro:

Dog dog;
using BarkFunction = void (*)(Dog*);
BarkFunction bark = MethodHelper<&Dog::bark>::call;
(*bark)(&dog); // or simply bark(&dog)

For methods with modifiers like const you might need some more specializations like:

template <class C, class Ret, class... Args, Ret (C::*m)(Args...) const> struct MethodHelper<m> {
    static Ret call(const C* object, Args... args) {
        return (object->*m)(args...);
    }
};
eyelash
  • 3,197
  • 25
  • 33
9

A function pointer to a class member is a problem that is really suited to using boost::function. Small example:

#include <boost/function.hpp>
#include <iostream>

class Dog 
{
public:
   Dog (int i) : tmp(i) {}
   void bark ()
   {
      std::cout << "woof: " << tmp << std::endl;
   }
private:
   int tmp;
};



int main()
{
   Dog* pDog1 = new Dog (1);
   Dog* pDog2 = new Dog (2);

   //BarkFunction pBark = &Dog::bark;
   boost::function<void (Dog*)> f1 = &Dog::bark;

   f1(pDog1);
   f1(pDog2);
}
Benjamin
  • 628
  • 1
  • 7
  • 13
8

Reason why you cannot use function pointers to call member functions is that ordinary function pointers are usually just the memory address of the function.

To call a member function, you need to know two things:

  • Which member function to call
  • Which instance should be used (whose member function)

Ordinary function pointers cannot store both. C++ member function pointers are used to store a), which is why you need to specify the instance explicitly when calling a member function pointer.

hrnt
  • 9,882
  • 2
  • 31
  • 38
  • 1
    I up voted this but would add a clarification point in case the OP doesn't know what you are referring to by "which instance". I would expand to explain the inherent 'this' pointer. – Eric Oct 25 '12 at 18:01
2

To create a new object you can either use placement new, as mentioned above, or have your class implement a clone() method that creates a copy of the object. You can then call this clone method using a member function pointer as explained above to create new instances of the object. The advantage of clone is that sometimes you may be working with a pointer to a base class where you don't know the type of the object. In this case a clone() method can be easier to use. Also, clone() will let you copy the state of the object if that is what you want.

Corwin Joy
  • 645
  • 7
  • 14
  • clones can be expensive and the OP may wish to avoid them if performance is an issue or of some concern. – Eric Oct 25 '12 at 17:58
2

I did this with std::function and std::bind..

I wrote this EventManager class that stores a vector of handlers in an unordered_map that maps event types (which are just const unsigned int, I have a big namespace-scoped enum of them) to a vector of handlers for that event type.

In my EventManagerTests class, I set up an event handler, like this:

auto delegate = std::bind(&EventManagerTests::OnKeyDown, this, std::placeholders::_1);
event_manager.AddEventListener(kEventKeyDown, delegate);

Here's the AddEventListener function:

std::vector<EventHandler>::iterator EventManager::AddEventListener(EventType _event_type, EventHandler _handler)
{
    if (listeners_.count(_event_type) == 0) 
    {
        listeners_.emplace(_event_type, new std::vector<EventHandler>());
    }
    std::vector<EventHandler>::iterator it = listeners_[_event_type]->end();
    listeners_[_event_type]->push_back(_handler);       
    return it;
}

Here's the EventHandler type definition:

typedef std::function<void(Event *)> EventHandler;

Then back in EventManagerTests::RaiseEvent, I do this:

Engine::KeyDownEvent event(39);
event_manager.RaiseEvent(1, (Engine::Event*) & event);

Here's the code for EventManager::RaiseEvent:

void EventManager::RaiseEvent(EventType _event_type, Event * _event)
{
    if (listeners_.count(_event_type) > 0)
    {
        std::vector<EventHandler> * vec = listeners_[_event_type];
        std::for_each(
            begin(*vec), 
            end(*vec), 
            [_event](EventHandler handler) mutable 
            {
                (handler)(_event);
            }
        );
    }
}

This works. I get the call in EventManagerTests::OnKeyDown. I have to delete the vectors come clean up time, but once I do that there are no leaks. Raising an event takes about 5 microseconds on my computer, which is circa 2008. Not exactly super fast, but. Fair enough as long as I know that and I don't use it in ultra hot code.

I'd like to speed it up by rolling my own std::function and std::bind, and maybe using an array of arrays rather than an unordered_map of vectors, but I haven't quite figured out how to store a member function pointer and call it from code that knows nothing about the class being called. Eyelash's answer looks Very Interesting..

Shavais
  • 2,476
  • 1
  • 27
  • 25
0

As a workaround/trick if you have control over the C API you could normally put a void* extra argument inside the C callback signature, afterward you will cast it (reinterpret_cast) to what you would expect.

IMAN4K
  • 1,265
  • 3
  • 24
  • 42