My problem of the day : how to designate a NON STATIC method of any class as a callback (i.e a method triggered by any event), without using Boost and others craps ?
Fortunately I was able to draw inspiration from this page (http://www.partow.net/programming/templatecallback) that offers an interesting template.
Only one problem left: to instantiate the callback object the client must still designate in the template argument type / name the class hosting the method that we wishes to designate as a callback, wich is quite annoying...
Therefore, I propose the following mod, involving inheritance on a callback interface class (BaseCallback) :
template <typename ReturnType, typename Parameter>
class BaseCallback
{
public:
virtual ReturnType operator()(Parameter parameter) = 0;
virtual ReturnType execute(Parameter parameter) = 0;
};
template <class Class, typename ReturnType, typename Parameter>
class CallBack : public BaseCallback<ReturnType, Parameter>
{
public:
typedef ReturnType (Class::*Method)(Parameter);
CallBack(Class* class_instance, Method method)
: class_instance_(class_instance),
method_(method)
{}
virtual ReturnType operator()(Parameter parameter)
{
return (class_instance_->*method_)(parameter);
}
virtual ReturnType execute(Parameter parameter)
{
return operator()(parameter);
}
private:
Class* class_instance_;
Method method_;
};
We have now a total decoupling between owner class callback method (client) and the calling class, it does not need to know the definition of the client class :-)
Here is a little example:
class Handler
{
protected:
CallBack<Handler, void, const std::string&>* m_cb;
public:
Handler( void )
{
m_cb = new CallBack<Handler, void, const std::string&>( this, &Handler::Func );
}
void Func( const std::string& a )
{
printf( "It works : %s\n", a.c_str() );
}
BaseCallback<void, const std::string&>* GetCallback( void )
{
return m_cb;
}
};
class EvtSource
{
protected:
BaseCallback<void, const std::string&>* m_handler;
public:
void RegisterHandler( BaseCallback<void, const std::string&>* p_handler )
{
m_handler = p_handler;
}
void DoSomething( void )
{
(*m_handler)( "test01" );
}
};
int main(int argc, char *argv[])
{
Handler e;
EvtSource foo;
foo.RegisterHandler( e.GetCallback() );
foo.DoSomething();
}
Enjoy ! ;-)
Aucun commentaire:
Enregistrer un commentaire