Reputation: 2494
I need to use a function defined in one class in another class. Instead of rewriting the whole function, I tried to pass the function as a pointer, as below:
class C {
public:
int get(int x) { return x*x; }
};
struct S {
int (*func) (int x);
};
int main() {
C c;
S s;
cout << c.get(3) << endl;
s.func = &C::get;
cout << s.func(3) << endl;
return 0;
}
This doesn't work and gives the following error:
func_ptr.cpp: In function ‘int main()’:
func_ptr.cpp:42:18: error: cannot convert ‘int (C::*)(int)’ to ‘int (*)(int)’ in assignment
Is it possible to do something like this, and if so, how can I fix it? Moreover, if it is possible, can I use the pointer from an object instance instead of the class? That is, to possibly use variables defined in a specific class instance. Thanks.
Upvotes: 0
Views: 1681
Reputation: 3153
If you're OK with using STL then you can utilize std::function to hold a pointer to a function and std::bind to bind that particular pointer to a particular function. It makes your code look much more cleaner. std::bind looks for both static and non-static member functions. For non-static member function would need to pass the object reference so it will be able to point to the correct address.
Here is a code snippet to show how to use it:
std::bind(ClassName::MemberFunctionName, object, std::placeholders::_1)
std::placeholders::_1 means that ::MemberFunctionName accepts one parameter.
Upvotes: 1
Reputation: 109089
C::get()
is a non-static member function, which means it must be invoked on an instance of C
. It has an implicit first argument, the this
pointer, that must be passed to it when calling the function.
Since your C::get()
doesn't seem to need access to any data members of C
, you could make it a static
member function.
static int get(int x) { return x*x; }
Now your code will work as is.
Another option is to change func
so that it is a pointer to a member function of C
struct S {
int (C::*func) (int x);
};
And invoke it as
s.func = &C::get;
std::cout << (c.*(s.func))(3) << std::endl;
Yet another option would be to change the type of S::func
to std::function<int(int)>
. Now it can hold any callable (function pointer, functor, lambda) that takes a single int
as an argument, and returns an int
.
struct S {
std::function<int(int)> func;
};
s.func = std::bind(&C::get, &c, std::placeholders::_1);
std::cout << s.func(3) << std::endl;
Upvotes: 7
Reputation: 582
A regular function and a member function are a bit different. To use a member function, you'll need an object to call it on (i.e. the this pointer in a member function body).
Take a look at std::function and std::bind, they are used to handle function like (callable) entities in a uniform way. They can manage global functions, static member functions, lambdas, regular member functions, functors, whatever that can be called like a function.
e.g.:
struct S
{
std::function<int(int)> func;
};
C c;
S s;
s.func = std::bind( &C::get, &c, std::placeholders::_1 );
Upvotes: 1