185

The question is the following: consider this piece of code:

#include <iostream>


class aClass
{
public:
    void aTest(int a, int b)
    {
        printf("%d + %d = %d", a, b, a + b);
    }
};

void function1(void (*function)(int, int))
{
    function(1, 1);
}

void test(int a,int b)
{
    printf("%d - %d = %d", a , b , a - b);
}

int main()
{
    aClass a;

    function1(&test);
    function1(&aClass::aTest); // <-- How should I point to a's aClass::test function?
}

How can I use the a's aClass::test as an argument to function1? I would like to access a member of the class.

Dr. Gut
  • 2,053
  • 7
  • 26
Jorge Leitao
  • 19,085
  • 19
  • 85
  • 121
  • 2
    Take a look at this answer http://stackoverflow.com/questions/2402579/c-function-pointer-to-member-function and also this C++ FAQ http://www.parashift.com/c++-faq/pointers-to-members.html – amdn Sep 30 '12 at 16:31
  • 17
    This is absolutely not a duplicate (at least not of the particular question that is linked). That question is about how to declare a member that is a pointer to a function; this is about how to pass a pointer to a non-static member function as a parameter. – CarLuva Jul 23 '14 at 15:12

9 Answers9

191

There isn't anything wrong with using function pointers. However, pointers to non-static member functions are not like normal function pointers: member functions need to be called on an object which is passed as an implicit argument to the function. The signature of your member function above is, thus

void (aClass::*)(int, int)

rather than the type you try to use

void (*)(int, int)

One approach could consist in making the member function static in which case it doesn't require any object to be called on and you can use it with the type void (*)(int, int).

If you need to access any non-static member of your class and you need to stick with function pointers, e.g., because the function is part of a C interface, your best option is to always pass a void* to your function taking function pointers and call your member through a forwarding function which obtains an object from the void* and then calls the member function.

In a proper C++ interface you might want to have a look at having your function take templated argument for function objects to use arbitrary class types. If using a templated interface is undesirable you should use something like std::function<void(int, int)>: you can create a suitably callable function object for these, e.g., using std::bind().

The type-safe approaches using a template argument for the class type or a suitable std::function<...> are preferable than using a void* interface as they remove the potential for errors due to a cast to the wrong type.

To clarify how to use a function pointer to call a member function, here is an example:

// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
    fptr(context, 17, 42);
}

void non_member(void*, int i0, int i1) {
    std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}

struct foo {
    void member(int i0, int i1) {
        std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
    }
};

void forwarder(void* context, int i0, int i1) {
    static_cast<foo*>(context)->member(i0, i1);
}

int main() {
    somefunction(&non_member, nullptr);
    foo object;
    somefunction(&forwarder, &object);
}
Dr. Gut
  • 2,053
  • 7
  • 26
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Ok, I like this answer! Can you please specify what you mean with "call your member through a forwarding function which obtains an object from the void* and then calls the member function", or share a useful link to it? Thanks – Jorge Leitao Sep 30 '12 at 16:44
  • I think I got it. (I've edited your post) Thanks for the explanation and example, really helpful. Just to confirm: for every member function that I want to point, I have to make a forwarder. Right? – Jorge Leitao Sep 30 '12 at 17:06
  • Well, yes, kind of. Depending on how effective you are using templates, you can get away with creating forwarding templates which can work with different classes and member functions. How to do this would be a separate function, I'd think ;-) – Dietmar Kühl Sep 30 '12 at 17:10
  • 3
    I dislike this answer because it uses `void*`, which means you can get very nasty bugs, because it is not typed checked anymore. – Superlokkus Sep 22 '15 at 08:35
  • @Superlokkus: can you please enlighten us with an alternative? – Dietmar Kühl Sep 22 '15 at 09:42
  • DietmarKühl see the answers below by PeterBecker and especially @MattPhillips – Superlokkus Sep 22 '15 at 12:31
  • @Superlokkus: Note that my answer mentions actually both of these approaches! It just explains in some detail how to actually do the dance calling a member function as doing so isn't directly obvious. – Dietmar Kühl Sep 22 '15 at 13:12
  • @DietmarKühl But your answer A) mentions the safe approaches only after the unsafe one in a very non-prominent way B) don't mentions the potential hazardous unsafe implications of your `void*`solution C) suggests with "your best option is to always pass a void* to your function" and `static_cast(context)->member(i0, i1);` this is the only solution and is safe, which is not We all know the problems caused by working around the type system, and your answer IMHO encourages this misuse. – Superlokkus Sep 22 '15 at 13:49
  • How would a template look like, that takes functions and non-static member functions? I am struggling ... Cheers! – germannp Jun 20 '16 at 11:32
  • @qiv: it seems that's a separate question... The simple answer is that you'd just pass a `template void f(Fun fun /*...*/)` and in the implementation of `f()` use the `fun` object with a suitable helper (e.g. `std::bind()` and call the function via the helper with suitable arguments. – Dietmar Kühl Jun 20 '16 at 12:10
  • What is the type of `object.*member`? As I understand if the member is not static method, than you can't pass it to some function and call. But in C++ if there is a type, then we can pass an object to the function. Or not? It would be cool to call something like `f(object.*member)` – Evgeny Jun 20 '23 at 09:57
  • 1
    @Evgeny: If `member` is a pointer to member `object.*member` is a reference to the corresponding member type. However, if `member` is a pointer to member function, `object.*member` can only be used as part of a call expression and it doesn't exist on its down (see the [Compiler Explorer demo](https://godbolt.org/z/o3GWzjfn8)). Conceptually, it would be version of the member function with the first parameter bound. You can create something like this using `std::bind(...)` but it isn't a language-level concept. – Dietmar Kühl Jun 22 '23 at 00:06
  • @DietmarKühl so then conceptually .* operator to member function is not an operator, and the real operator is `.*()` ? – Evgeny Jun 22 '23 at 15:28
  • @Evgeny: I guess, in some sense this is correct. There is simply no object in the C++ core language to represent the intermediate result. Maybe it wouldn’t be entirely unreasonable to return a suitably bound library object but it seems pointer to members aren’t used as often. – Dietmar Kühl Jun 22 '23 at 18:53
135

@Pete Becker's answer is fine but you can also do it without passing the class instance as an explicit parameter to function1 in C++ 11:

#include <functional>
using namespace std::placeholders;

void function1(std::function<void(int, int)> fun)
{
    fun(1, 1);
}

int main (int argc, const char * argv[])
{
   ...

   aClass a;
   auto fp = std::bind(&aClass::test, a, _1, _2);
   function1(fp);

   return 0;
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Matt Phillips
  • 9,465
  • 8
  • 44
  • 75
  • 1
    Is `void function1(std::function)` correct? – Deqing Apr 09 '15 at 01:51
  • 4
    You need to give the function argument a variable name and then the variable name is what you actually pass. So: `void function1(std::function functionToCall)` and then `functionToCall(1,1);`. I tried to edit the answer but someone rejected it as not making any sense for some reason. We'll see if it gets upvoted at some point. – Dorky Engineer Apr 09 '15 at 05:52
  • 1
    @DorkyEngineer That's pretty weird, I think you must be right but I don't know how that error could have gone unnoticed for so long. Anyway, I've edited the answer now. – Matt Phillips Apr 09 '15 at 07:11
  • 4
    I found this [post](http://stackoverflow.com/questions/14677997/stdfunction-vs-template) saying that there is a severe performance penalty from std::function. – kevin Jun 28 '15 at 21:56
  • 3
    @kevin, you may want to revise your comment, as that post's answers showed a flaw in the benchmark. – Jorge Leitao Jan 03 '20 at 08:53
  • 1
    Great answer - this is exactly what I was looking for. One small detail though - I believe it should be: ```auto fp = std::bind(&aClass::test, &a, _1, _2);``` If you don't pass the class instance as a reference, it looks like the compiler (at least MSVC2019) tries to move it which it probably not what you want. See also the example [here (auto f3 = ...)](https://en.cppreference.com/w/cpp/utility/functional/bind). – James S. Apr 11 '20 at 18:56
64

A pointer to member function is different from a pointer to function. In order to use a member function through a pointer you need a pointer to it (obviously ) and an object to apply it to. So the appropriate version of function1 would be

void function1(void (aClass::*function)(int, int), aClass& a) {
    (a.*function)(1, 1);
}

and to call it:

aClass a; // note: no parentheses; with parentheses it's a function declaration
function1(&aClass::test, a);
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • 1
    Thank you very much. I just found out that brackets count here:function1(&(aClass::test), a) works with MSVC2013 but not with gcc. gcc needs the & directly in front of the class name (which I find confusing, because the & operator takes the address of the function, not of the class) – Markus Sabin Mar 01 '16 at 13:06
  • 1
    I thought `function` in `void (aClass::*function)(int, int)` was a type, because of it is a type in `typedef void (aClass::*function)(int, int)`. – Olumide Nov 09 '17 at 16:38
  • 1
    @Olumide — `typedef int X;` defines a type; `int X;` creates an object. – Pete Becker Nov 09 '17 at 17:01
16

Since 2011, if you can change function1, do so, like this:

#include <functional>
#include <cstdio>

using namespace std;

class aClass
{
public:
    void aTest(int a, int b)
    {
        printf("%d + %d = %d", a, b, a + b);
    }
};

template <typename Callable>
void function1(Callable f)
{
    f(1, 1);
}

void test(int a,int b)
{
    printf("%d - %d = %d", a , b , a - b);
}

int main()
{
    aClass obj;

    // Free function
    function1(&test);

    // Bound member function
    using namespace std::placeholders;
    function1(std::bind(&aClass::aTest, obj, _1, _2));

    // Lambda
    function1([&](int a, int b) {
        obj.aTest(a, b);
    });
}

(live demo)

Notice also that I fixed your broken object definition (aClass a(); declares a function).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
7

I asked a similar question (C++ openframeworks passing void from other classes) but the answer I found was clearer so here the explanation for future records:

it’s easier to use std::function as in:

 void draw(int grid, std::function<void()> element)

and then call as:

 grid.draw(12, std::bind(&BarrettaClass::draw, a, std::placeholders::_1));

or even easier:

  grid.draw(12, [&]{a.draw()});

where you create a lambda that calls the object capturing it by reference

Nicola Bertelloni
  • 333
  • 1
  • 3
  • 17
  • 1
    Given that this is tagged CPP I think this is the cleanest solution. We could use a constant reference to `std::function` in `draw` though instead of copying it on every call. – Sohaib Aug 28 '19 at 10:18
  • 2
    The placeholder should not be used in this example as the function does not takes any params. – kroiz Sep 03 '19 at 06:34
  • Note that as of C++14 lambdas should be prefered to std::bind for a couple of reasons (see e.g. "Effective Modern C++", Item 34: Prefer lambdas to std::bind) – Bim Mar 31 '22 at 07:55
7

Important to note that unless you can change the signature of the code taking the function, there is no (easy) way to do this. That would be trying to implement a closure in a language that does not have closures that are the same as functions (the signature for a closure in C++ is different).

There are two actual ways to achieve this:

  1. Use some sort of singleton/global variable that you store the closure in, and then pass a helper function that calls the needed function using that closure. Here is an example:
#include <stdio.h>

template<class C, typename ReturnType, typename... Args>
class ClosureSingleton {
    typedef ReturnType (C::*FuncType)(Args...);

   public:
    static ClosureSingleton& getInstance() {
        static ClosureSingleton instance;
        return instance;
    }

    void setClosure(C* obj, FuncType f) {
        this->obj      = obj;
        this->function = f;
    }
    static ReturnType funcPtr(Args... args) {
        C* obj    = getInstance().obj;
        auto func = getInstance().function;

        return (obj->*func)(args...);
    }

   private:
    ClosureSingleton() {}

    C* obj;
    FuncType function;

   public:
    ClosureSingleton(ClosureSingleton const&) = delete;
    void operator=(ClosureSingleton const&)   = delete;
};

class aClass {
   public:
    void aTest1(int a, int b) { printf("%d + %d = %d\n", a, b, a + b); }
    int aTest2(int a, int b) { return a + b; }
};

void function1(void (*function)(int, int)) {
    function(1, 1);
}
int function2(int (*function)(int, int)) {
    return function(1, 1);
}

int main() {
    aClass tmp;
    ClosureSingleton<aClass, void, int, int>::getInstance().setClosure(
        &tmp, &aClass::aTest1);
    function1(&ClosureSingleton<aClass, void, int, int>::funcPtr);

    ClosureSingleton<aClass, int, int, int>::getInstance().setClosure(
        &tmp, &aClass::aTest2);
    printf(
        "function2: %d\n",
        function2(&ClosureSingleton<aClass, int, int, int>::funcPtr));

    return 0;
}

Of course, this has the obvious downside that the closure needs to be set before every call, as well as some thread safety issues. Not ideal, but potentially workable in specific circumstances

  1. Use something like asmjit or dynamic compilation to dynamically compile and pass the function in to the C code. This will only work on machines that allow heap section to be marked as executable. It is also very much non-portable as you will be writing assembly code to accomplish this. However, if you get it working, you will indeed have a true closure, albeit a substantially higher cost to creating the closure compared to how most programming languages implement closures (they do not duplicate the function assembly, instead they use a context object)
  2. Patch the lib/dll that has the function handler to change it's signature to allow a context object. Again, a very brittle and non optimal solution.

My original answer, which does not really answer the question, but people found it useful:

Not sure why this incredibly simple solution has been passed up:

#include <stdio.h>

class aClass
{
public:
    void aTest(int a, int b)
    {
        printf("%d + %d = %d\n", a, b, a + b);
    }
};

template<class C>
void function1(void (C::*function)(int, int), C& c)
{
    (c.*function)(1, 1);
}
void function1(void (*function)(int, int)) {
  function(1, 1);
}

void test(int a,int b)
{
    printf("%d - %d = %d\n", a , b , a - b);
}

int main (int argc, const char* argv[])
{
    aClass a;

    function1(&test);
    function1<aClass>(&aClass::aTest, a);
    return 0;
}

Output:

1 - 1 = 0
1 + 1 = 2
Asad-ullah Khan
  • 1,573
  • 18
  • 22
0

I made the member function as static and all works:

#include <iostream>

class aClass
{
public:
    static void aTest(int a, int b)
    {
        printf("%d + %d = %d\n", a, b, a + b);
    }
};

void function1(int a,int b,void function(int, int))
{
    function(a, b);
}

void test(int a,int b)
{
    printf("%d - %d = %d\n", a , b , a - b);
}

int main (int argc, const char* argv[])
{
    aClass a;

    function1(10,12,test);
    function1(10,12,a.aTest); // <-- How should I point to a's aClass::test function?

    getchar();return 0;
}
mathengineer
  • 140
  • 6
  • Not only solve to the main question "How can I use the a's aClass::test as an argument to function1?" but also it is recommended to avoid modify class private variables using code external to the class – mathengineer Dec 15 '18 at 16:01
0

If you actually don't need to use the instance a (i.e. you can make it static like @mathengineer 's answer) you can simply pass in a non-capture lambda. (which decay to function pointer)


#include <iostream>

class aClass
{
public:
   void aTest(int a, int b)
   {
      printf("%d + %d = %d", a, b, a + b);
   }
};

void function1(void (*function)(int, int))
{
    function(1, 1);
}

int main()
{
   //note: you don't need the `+`
   function1(+[](int a,int b){return aClass{}.aTest(a,b);}); 
}

Wandbox


note: if aClass is costly to construct or has side effect, this may not be a good way.

apple apple
  • 10,292
  • 2
  • 16
  • 36
-3

You can stop banging your heads now. Here is the wrapper for the member function to support existing functions taking in plain C functions as arguments. thread_local directive is the key here.

http://cpp.sh/9jhk3

// Example program
#include <iostream>
#include <string>

using namespace std;

typedef int FooCooker_ (int);

// Existing function
extern "C" void cook_10_foo (FooCooker_ FooCooker) {
    cout << "Cooking 10 Foo ..." << endl;
    cout << "FooCooker:" << endl;
    FooCooker (10);
}

struct Bar_ {
    Bar_ (int Foo = 0) : Foo (Foo) {};
    int cook (int Foo) {
        cout << "This Bar got " << this->Foo << endl;
        if (this->Foo >= Foo) {
            this->Foo -= Foo;
            cout << Foo << " cooked" << endl;
            return Foo;
        } else {
            cout << "Can't cook " <<  Foo << endl;
            return 0;
        }
    }
    int Foo = 0;
};

// Each Bar_ object and a member function need to define
// their own wrapper with a global thread_local object ptr
// to be called as a plain C function.
thread_local static Bar_* Bar1Ptr = NULL;
static int cook_in_Bar1 (int Foo) {
    return Bar1Ptr->cook (Foo);
}

thread_local static Bar_* Bar2Ptr = NULL;
static int cook_in_Bar2 (int Foo) {
    return Bar2Ptr->cook (Foo);
}

int main () {
  Bar1Ptr = new Bar_ (20);
  cook_10_foo (cook_in_Bar1);
  
  Bar2Ptr = new Bar_ (40);
  cook_10_foo (cook_in_Bar2);
  
  delete Bar1Ptr;
  delete Bar2Ptr;
  return 0;
}

Please comment on any issues with this approach.

Other answers fail to call existing plain C functions: http://cpp.sh/8exun

Necktwi
  • 2,483
  • 7
  • 39
  • 62
  • 7
    So instead of using std::bind or a lambda to wrap the instance you rely on a global variable. I can not see any advantage to this approach compared to the other answers. – super Aug 07 '18 at 10:57
  • @super, Other answers can not call existing functions taking in plain `C` functions as arguments. – Necktwi Aug 07 '18 at 13:55
  • 5
    The question is how to call a member function. Passing in a free function is already working for OP in the question. You are also not passing in anything. There's only hard coded functions here and a global Foo_ pointer. How would this scale if you want to call a different member function? You would have to rewrite the underlying functions, or use different ones for each target. – super Aug 07 '18 at 14:59