C++ Passing pointer to non-static member function

2019-03-03 09:30发布

问题:

Hi everyone :) I have a problem with function pointers
My 'callback' function arguments are:
1) a function like this: int(*fx)(int,int)
2) an int variable: int a
3) another int: int b
Well, the problem is that the function I want to pass to 'callback' is a non-static function member :( and there are lots of problems
If someone smarter than me have some time to spent, he can look my code :)

#include <iostream>
using namespace std;

class A{
private:
    int x;
public:
    A(int elem){
        x = elem;
    }

    static int add(int a, int b){
        return a + b;
    }

    int sub(int a, int b){
        return x - (a + b);
    }
};

void callback( int(*fx)(int, int), int a, int b)
{
    cout << "Value of the callback: " << fx(a, b) << endl;
}

int main()
{
A obj(5);

    //PASSING A POINTER TO A STATIC MEMBER FUNCTION -- WORKS!!
    // output = 'Value of the callback: 30'
    callback(A::add, 10, 20);

    //USING A POINTER TO A NON-STATIC MEMBER FUNCTION -- WORKS!!
    int(A::*function1)(int, int) = &A::sub;
    // output = 'Non static member: 3'
    cout << "Non static member: " << (obj.*function1)(1, 1) << endl;

    //PASSING A POINTER TO A NON-STATIC MEMBER FUNCTION -- aargh
    // fallita! tutto quello sotto non funziona --> usa i funtori???
    // puoi creare una classe wrapper ma non riuscirai mai a chiamare da callback
    int(A::*function2)(int, int) = &A::sub;
    int(*function3)(int, int) = obj.*function2; //[error] invalid use of non-static member function
    callback(function3, 1, 1);
}

There's a way to create my pointer in the way I tried to wrote, like int(*fx)(int, int) = something?
I searched a lot but no-one could gave me an answer (well, there was an answer: "NO", but I still think I can do something)

I heard also about functors, may them help me in this case?

Thanks to anyone
PS: sorry for my bad english

EDIT1: I can use something like this:

template <class T>
void callback2( T* obj, int(T::*fx)(int, int), int a, int b)
{
    cout << "Value of the callback: " << (obj->*fx)(a, b) << endl;
}
void callback2( void* nullpointer, int(*fx)(int, int), int a, int b)
{
    cout << "Value of the callback: " << fx(a, b) << endl;
}

and in my main:

callback2(NULL, &mul, 5, 3); // generic function, it's like: int mul(int a, int b){return a*b;}
callback2(NULL, &A::add, 5, 3); //static member function
callback2(&obj, &A::sub, 1, 1); //non static member function

I'm not completely sadisfied, because I don't want to pass my 'callback2' the first parameter (the object)...
The question, for people that didn't understand my (bad) explanation, is: can I delete the first parameter in my callback2 function?
the prototype will be

void callback2(int(*fx)(int, int), int a, int b)<br>

and I will call like this:

callback2(&obj.sub, 1, 3);

回答1:

Functions cannot be referenced this way:

int (*function3)(int, int) = obj.*function2;

You have to pass the address of the function like this:

int (*function3)(int, int) = std::mem_fn(&A::sub, obj);
//                           ^^^^^^^^^^^^^^^^^^^^^^^^^

The expression function2 decays into a pointer-to-function which allows it to work.



回答2:

I would do it with std functors, here is a simple example based off of your code:

#include <iostream>
#include <functional>
using namespace std;

class A{
private:
    int x;
public:
    A(int elem){
        x = elem;
    }

    static int add(int a, int b){
        return a + b;
    }

    int sub(int a, int b) const{
        return x - (a + b);
    }
};

void callback( std::function<int(const A& ,int,int )> fx, A obj, int a, int b)
{
    cout << "Value of the callback: " << fx( obj, a, b) << endl;
}

int main()
{
A obj(5);


    std::function<int(const A& ,int,int )> Aprinter= &A::sub;

    callback(Aprinter,obj,1,2);
}