Click to See Complete Forum and Search --> : function call
Tommy Wiklund
May 16th, 2002, 01:08 PM
Hi Gurus,
I would like a class with a member function that is able to receive
any another class member function as an argument.
This to be able to callback anyone who calls.
Don't know how to do this, hope for a sample or a push in the right direction.
Thanks in advance /Tommy
jfaust
May 16th, 2002, 01:39 PM
Do some research on template member functions, as in member functions that are templates in a non-template class.
Basically, you'll need to store the class pointer and an offset to the member function.
All of the callbacks will need to have the same number of arguments.
I've used this before, but would be hard pressed to come up with an example.
Jeff
crupp
May 16th, 2002, 03:26 PM
Hi Tommy,
this is quite complicated :( Pointers to member functions are tricky because you always need a valid 'this'-pointer to an object on which the member is invoked (as long as the member is not static).
If you really want to use this then search for 'functors'. You can find some here: http://www.crupp.de/prj/EventSystem.cpp.html
It's a message queue system with callback functions. Maybe it helps...
cu
Chris :)
Stefan Langemark
May 16th, 2002, 04:22 PM
I think some templates and inheritance will do the trick, but it will not be pretty... take a deep breath
class CallbackBase {
public:
CallbackBase() {}
virtual ~CallbackBase() {}
};
// My c++ grammar is a bit shaky on pointers to member
// functions and how to use them, but here is a try:
template <class T>
class Callback : public CallbackBase {
public:
Callback(T* obj, void (T::*memberFunc) ())
: _obj(obj), _memberFunc(memberFunc)
{}
void Notify()
{
// call member function using _obj and _memberFunc
_obj->(*_memberFunc)();
}
private:
T* _obj;
void (T::*_memberFunc) ();
};
// To use this stuff:
void
MyClass::CallbackAtOnce(CallbackBase *cb)
{
cb->Notify();
delete cb;
}
void
CallingClass::TestCallback()
{
MyClass myClass;
myClass.CallbackAtOnce(
new Callback<CallingClass>(this, CallbackFunc)
);
}
void
CallingClass::CallbackFunc()
{
cout << "Finally there!" << endl;
}
By using a non-template base class it is possible to handle the callback function object as a CallbackBase object. Someone may please tell me an easier way to do this stuff, but this is the best I have come up with (yet)...
Good luck :)
/Stefan
sidy
May 16th, 2002, 06:17 PM
Implementing callbacks are very easy once you understand the basic mechanism.
First you need to declare a static method in your class:
Class CMyClass
{
static void __cdecl myThreadWrapper(LPVOID);
};
Then in the class file, declare the method:
void CMyClass::myThreadWrapper(LPVOID ptr)
{
CMyClass * mySelf=(CMyClass *)ptr;
CMyNewClass *pMyThread = new CMyNewClass();
pMyThread->MyMethod();
delete pMyThread;
}
Then, in the method that requires the callback, use the & operator and stick the static method name into the function, in this case I used the WIN32 thread call and pass a pointer to the "this" object.
void CMyClass::MethodThatHasACallBack()
{
..
do stuff
..
_beginthread( &myThreadWrapper, 0, this );
}
Most Important is that you must pass the this pointer!
Hope this helps!
ankursaxena
May 16th, 2002, 08:21 PM
Stefan Langemark
So basically this is how you would acheive the event model used in java swnig?? i mean this would be equivalent in c++ is it??
sidy
May 16th, 2002, 08:31 PM
Howdy,
I ripped this straight out of production C++ code... I would not imagine Java to have a problem with callbacks.
Sid
Stefan Langemark
May 17th, 2002, 02:07 AM
Of course it is also possible to make callbacks the easy (traditional, boring?) way by declaring an interface (class) with only one virtual abstract member and then letting all classes that want callbacks implement that interface. Then you only need to pass the interface pointer around... But then the name of the callback function is of course fixed. This is also the beginning of the observer pattern...
ankursaxena, I do not use Java or Swing, so I am not the right person to compare it with c++ :)
/Stefan
Graham
May 17th, 2002, 03:33 AM
It all depends on why you want the callback. There are a number of design patterns that might be relevant:
1) Chain of responsibility. Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.
2) Command. This encapsulates a request as an object, allowing you to parameterise clients with different requests, queue or log requests, and support undoable operation
3)Mediator. Define an object that encapsulates how a set of objects interact.
4) Observer. Define a one-to-many dependency between objects, so that when one object changes state, all its dependents are notified.
5) Visitor. (Possibly) Extend the operations that can be performed on/by a class hierarchy without extending the class interfaces.
(All descriptions taken from the GoF book).
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.