#include <iostream>
#include <vector>
using namespace std;
class Func
{
public:
int (*function) (void);
Func(int (*Afunc) (void))
{
function = Afunc;
}
};
class A
{
public:
int var;
vector<Func> callBacks;
void Register(int (*f) (void))
{
callBacks.push_back(Func(f));
}
};
class B
{
public:
int stuff;
int CallMe(void)
{
cout << "I was called" << endl;
}
};
class C
{
public:
int stuff;
int CallMe(void)
{
cout << "I was called also" << endl;
}
};
int main()
{
A myA;
B myB;
C myC;
myA.Register( (int (*) (void)) B::CallMe); // compile error
myA.Register( (int (*) (void)) C::CallMe); // compile error
myA.callBacks[0].function();
myA.callBacks[1].function();
return 0;
}
Creating callbacks
I am trying to implement a system of callbacks and I cant get it to compile. Can someone help me figure this out? I want a class to have a vector of function pointers that will be called when an event occurs. Similar to Windows.
The CallMe functions of classes B and C have another signature than you might have expected, because the compiler adds the implicit this parameter.
Your "CallMe" functions are scoped to their respective classes, where the Function pointer definition is for a C function pointer.
Also, Your "CallMe" functions require a return value, which you have not specified.
You can fix the callback issues by:
1: Make your callbacks global.
2: Make them static.
3: Create a wrapper class to call them.
4: Use a functor.. which is sort of similar to what you're already doing with Func.
I highly recommend This page. Specifically, the sections titled "How to Implement a Callback to a static/non-static C++ Member Function"
Also, Your "CallMe" functions require a return value, which you have not specified.
You can fix the callback issues by:
1: Make your callbacks global.
2: Make them static.
3: Create a wrapper class to call them.
4: Use a functor.. which is sort of similar to what you're already doing with Func.
I highly recommend This page. Specifically, the sections titled "How to Implement a Callback to a static/non-static C++ Member Function"
... which means things get alot more tricky. Keywords to look for : member-function-pointers for the basics and Functors to impliment callbacks.
Just to give you a preview:
In order to call a non-static member-function from a function pointer, you will need supply a pointer to the object who's method you want to call, and the syntax for declaring member-function pointers is a little bit different.
Of course this wont give you all the answers you need, but maybe help you search in the right direction.
Just to give you a preview:
In order to call a non-static member-function from a function pointer, you will need supply a pointer to the object who's method you want to call, and the syntax for declaring member-function pointers is a little bit different.
// So this:Func(int (*Afunc) (void))// becomesFunc (const SomeClass* pObject, int (SomeClass::*pMethod) (void))// and you all it like this(pObject->*pMethod) ()
Of course this wont give you all the answers you need, but maybe help you search in the right direction.
Okay thanks for the help, I know what I need to read more about. What if in my previous example B and C were derived from an abstract class with the pure virtual function CallMe. Then wouldnt the signiture for CallMe() be the same in class B and C?
Quote:Original post by Graham
Okay thanks for the help, I know what I need to read more about. What if in my previous example B and C were derived from an abstract class with the pure virtual function CallMe. Then wouldnt the signiture for CallMe() be the same in class B and C?
What would you put into your vector ?
You may either chose to put pointers to instances of the abstract base class in your vector, but then you need to take care of deleting all those objects afterwards. But that would require you to know the runtime type of the object.
The best option would be to use a functor, as already mentioned.
Quote:Then wouldnt the signiture for CallMe() be the same in class B and C?
You actually don't need it to be the same. You can just cast it to the right type*
class A{public: void foo (int);};class B{public: void foo (int);};class CallBack{public: typedef const void* ObjectPtr; typedef void (CallBack::*MethodPtr)(int); CallBack (ObjectPtr pObject, MethodPtr pMethod) { m_pObject = pObject; m_pMethod = pMethod; } void invoke (int i) { (m_pObject->*m_pMethod) (i); } private: ObjectPtr m_pObject; MethodPtr m_pMethod;}...// in main A a; B b; CallBack callbackA = CallBack (reinterpret_cast <CallBack::ObjectPtr>(&a), reinterpret_cast <CallBack::MethodPtr>(&A::foo)); CallBack callbackB = CallBack (reinterpret_cast <CallBack::ObjectPtr>(&b), reinterpret_cast <CallBack::MethodPtr>(&B::foo));
But in all honesty having to use those casts everywhere kindof sucks, so this is a great place for templates... (if you arn't very comfortable with them just stkip this.
class CallBack{public: typedef const void* ObjectPtr; typedef void (CallBack::*MethodPtr)(int); template <class CLASS> CallBack (const CLASS* pObject, void (CLASS::*pMethod)(int) ) { m_pObject = reinterpret_cast <ObjectPtr> (pObject); m_pMethod = reinterpret_cast <MethodPtr> (pMethod); } ......// in main A a; B b; CallBack callbackA = CallBack (&a, &A::foo); CallBack callbackB = CallBack (&b, &B::foo);
Much better... of course from there you can templatize parameters and return types but that goes beyond the scope of this post.
*You can only cast between different types of member-function pointers if they have the same size. They only have the same size IF they use the same inheritance OR you use the /vmg compiler option in MSVC++.
Hope that helps a little.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement