Reputation: 28
Is it possible to save a pointer to a class method in a variable of this or another class? If this is not possible, I would also like to know why.
It is possible to create a variable outside the class, and assign a class method to it. Also call this method. But with the inclusion of this variable as a class field, the example stops working.
It is also possible to call this method in the class itself with the this pointer. Why does this work like that?
Not working example. Desired result
#include <iostream>
using namespace std;
class B {
public:
typedef void (B::*function_type)(void);
B::function_type _func;
B() {
cout << "B" << endl;
}
void foo(){
cout << "B foo" << endl;
}
};
int main()
{
B b;
b._func = &B::foo;
(b.*_func)();
}
Call inside class working
#include <iostream>
#include <functional>
using namespace std;
class B {
public:
typedef void (B::*function_type)(void);
B::function_type _func;
B() {
cout << "B" << endl;
}
void foo(){
cout << "B foo" << endl;
}
void run() {
(this->*_func)();
}
};
int main()
{
B b;
b._func = &B::foo;
b.run();
}
I would like to save a class method and call it through an object.
Upvotes: 0
Views: 99
Reputation: 1368
Your first example (the one that does not work) can work only if you are referring to a static function because the static methods can be called without a calling object instance that corresponds in your case to (b.*(b._func))();
So, you can write :
class B {
public:
typedef void (*function_type)(void);
function_type _func;
B() { cout << "B" << endl;}
static void foo(){ cout << "B foo" << endl; }
};
int main()
{
B b;
b._func = &B::foo;
(b._func) ();
}
Upvotes: 0
Reputation: 76498
There are two objects involved in calling your _func
pointer. One is the object that the function should be applied to, and one is the object that holds the pointer. When you're inside a member function, the first one is implied; it's the internal this
pointer. So (this->*_func)()
calls the data member _func
on the current object. When you're outside a member function you have to supply both objects:
(b.*b._func)();
The b
on the left is like the this->
in the first version: it tells the compiler what object to apply the function too. The second b
is the object that holds the pointer.
If that's thoroughly confusing, change the situation a bit. Use two B
objects and play with which one is which:
B b;
B b1;
(b.*b1.func)();
(b1.*b.func)();
Upvotes: 3
Reputation: 75874
It is possible. The syntax is a little bit scary though:
(b.*(b._func))();
Why is it like that? Well, first you need to refer to the data member _func
of object b
. That is b._func
. Next you need to call that data member as a data function pointer which is the (b.*(..))()
part.
I would suggest to simplify the calling side by creating a method that does the crazy call syntax stuff:
class B {
// ...
void call_me()
{
(this->*(_func))();
}
};
b.call_me();
Some tips to improve:
Use using
instead of typedef
:
using function_type = void (B::*)(void);
And you don't need B::function_type
. Just function_type
is enough because you are inside the scope of the class.
Upvotes: 1