I'm trying to setup a function pointer that is set during execution based on a set of user parameters. I would like to have the function pointer point to a non-static member function but I can't find how to do it.
The examples I've seen say this can only be done with static member function only or use global variables in straight C.
A simplified example follows:
class CA
{
public:
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(double f(const double), double x) {
char cTemp[256];
sprintf_s(cTemp, "Value = %f", f(x));
std::cout << cTemp;
};
private:
double a, b;
};
The implementation part is
CA cA;
cA.setA(1.0);
cA.setB(2.0);
double (*p)(const double);
if(true) {
p = &cA.getA; //'&' : illegal operation on bound member function expression
} else {
p = cA.getB; //'CA::getB': function call missing argument list; use '&CA::getB' to create a pointer to member
//'=' : cannot convert from 'double (__thiscall CA::* )(const double)' to 'double (__cdecl *)(const double)'
}
cA.print(p, 3.0);
So how do I get p to point to either 'getA' or 'getB' so that it is still useable by 'print'.
From what I have seen, the suggestions are to use boost or std::bind but I've had no experience with either of these. I'm hoping that I don't need to dive into these and that I'm just missing something.
Compiler MSVC++ 2008
The compiler supplies a special implicit pointer named this that allows a member function to access the non- static data members. The this pointer contains the address of the object that called the member function.
You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.
The 'this' pointer is passed as a hidden argument to all nonstatic member function calls and is available as a local variable within the body of all nonstatic functions. 'this' pointer is not available in static member functions as static member functions can be called without any object (with class name).
You either have to use a pointer to member, or a free function.
Don't forget that a member function accepts an implicit this
parameter: therefore, a member function accepting a double
can't be the same thing as a non-member (free) function accepting a double
.
// OK for global functions
double (*p)(const double);
// OK for member functions
double (CA:*p)(const double);
Also the way you invoke them is different. First of all, with member functions, you need an object to invoke them on (its address will eventually be bound to the this
pointer in the function call). Second, you need to use the .*
operator (or the ->*
operator if you are performing the call through a pointer):
p = &CA::getA;
CA cA;
(cA.*p)();
Consistently, you will have to change your definition of function print()
:
#include <iostream>
void print(double (CA::*f)(const double), double x)
{
// Rather use the C++ I/O Library if you can...
std::cout << "Value = " << (this->*f)(x);
};
So finally, this is how you should rewrite your main()
function:
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
double (CA::*p)(const double);
if (true) // Maybe use some more exciting condition :-)
{
p = &CA::getA;
}
else {
p = &CA::getB;
}
cA.print(p, 3.0);
}
This answer focuses on the compilation issue presented in the question. I would not recommend implementing this as a solution.
Pointers to member functions are best dealt with with typedef
s and a macro.
Here's the macro for calling a member function:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
Source: [33.6] How can I avoid syntax errors when calling a member function using a pointer-to-member-function?, C++ FAQ.
This saves you having to remember the ugly (object).*(ptrToMember)
syntax any time you wish to call a member function by pointer.
In your class
, declare a typedef
called CAGetter
, this will make variable declaration much simpler:
class CA
{
public:
typedef double (CA::*CAGetter)(const double x);
Then you can declare your print()
function quite simply:
void print(CAGetter f, double x)
The body is also simple, clear and concise:
{
std::cout << "value = " << CALL_MEMBER_FN(*this, f)(x) << '\n';
}
Sample usage:
CA a;
a.setA(3.1);
a.setB(4.2);
// Using a variable...
CA::CAGetter p = &CA::getA;
a.print(p, 1);
// without a variable
a.print(&CA::getB, 1);
// Calling the functions from outside the class...
std::cout << "From outside (A): " << CALL_MEMBER_FN(a, p)(10) << std::endl;
std::cout << "From outside (B): " << CALL_MEMBER_FN(a, &CA::getB)(10) << std::endl;
Passing a pointer to a member function into a method of an instance of the same class is a design smell (you wouldn't normally pass a member variable to a method, this is no different). There is not enough information in this question to address the underlying design issue but this problem could probably be solved with separate print()
methods, a member variable or with inheritance and polymorphism.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With