Question

I am trying to pass a member function of class A to a global function as parameter. What must I do to make this work? Also, is this a good idea? Context: I want to do this because (the synonym) doSomething(...) is a very general function that is used in main() as well as in different classes. Thus I can avoid to have several copies of the same code in my Project. What are alternatives (if it's not optimal)?

#include <iostream>
using namespace std;

double doSomething(int i, double (*f)(double)) { return (*f)(i); }

class A{
public:
    A(double x) : number(x) {}
    double times(double i) { return ::doSomething(i, &A::multiply);} //calles the global function and gives a member function as parameter
    double multiply(double i) {return number*i;}
private:
    double number;
};

int main() {

    A obj(5.0);
    cout << obj.times(3.5) <<endl;

    return 0;
}

Compiler complains:

../src/test5.cpp: In member function ‘double A::times(double)’:
../src/test5.cpp:17:63: error: cannot convert ‘double (A::*)(double)’ to ‘double (*)(double)’ for argument ‘2’ to ‘double doSomething(int, double (*)(double))’
  double times(double i) { return ::doSomething(i, &A::multiply);} //calles the global function and gives a parameter member function as parameter
                                                               ^
../src/test5.cpp:17:65: warning: control reaches end of non-void function [-Wreturn-type]
  double times(double i) { return ::doSomething(i, &A::multiply);} //calles the global function and gives a parameter member function as parameter
Was it helpful?

Solution

Your doSomething function expects a free function pointer (free function means non-member function). You try to pass a member function pointer to it. This will not work. Why? When you have a free function, say void f(double), you can simply call it:

f(3.14);

on the other hand, when you have a member (and non-static) function, to call it you need an object, e.g.:

obj.m(3.14);

and you cannot call a member function without an object. So a member function cannot be used interchangeably with free function, since they are called in different way. Think about the (*f)(i) call in the doSomething function - what would be the A object for multiply to call upon?

Your design needs rethinking. If you want to share code, maybe you need some class hierarchy and the common code in the base class?

OTHER TIPS

With C++11 you might do:

#include <functional>

typedef std::function<double (double)> do_something_function;
double doSomething(double i, do_something_function f) { return f(i); }

class A{
    public:
    A(double x) : number(x) {}
    double times(double i) {
        do_something_function f = [this] (double i) {
            return this->multiply(i);
        };
        return ::doSomething(i, f);
    }
    double multiply(double i) {
        return number * i;
    }

    private:
    double number;
};

The way you call a non-static function member of a class via pointer differs from the way you do it on freestanding function because a pointer to instance is needed.

#include <iostream>
using namespace std;

class A;
typedef double (A::*f)(double);
double doSomething(double i, f p, A* ap);

class A {
public:

    A(double x) : number(x) {
    }

    double times(double i) {
        return ::doSomething(i, &A::multiply, this);
    } //calles the global function and gives a member function and pointer to A

    double multiply(double i) {
        return number*i;
    }
private:
    double number;
};

double doSomething(double i, double (A::*fp)(double), A* ap) {
    return (ap->*fp)(i);  // call *fp on *ap
}

int main() {

    A obj(5.0);
    cout << obj.times(3.5) << endl;

    return 0;
}

example

it is tricky of programing -- convert a non-static member function into a global function refer to the source code : https://github.com/shenxiaolong-code/processInternalExplorer/blob/master/sources/SystemExplorer/include/SystemExplorer/callback_cpp2c.h

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top