#include <iostream>
#include <list>
#include <string>
// Una clase base para hacer clases con callbacks:
class callbackbase {
public:
virtual void operator()() const { std::cout <<"callbackbase()" <<std::endl; };
virtual ~callbackbase() { };
};
// El functor que implementa la funcionalidad del callback:
template <class T> class callback : public callbackbase {
public:
typedef void (T::*Func)();
callback( T& t, Func func ) : object(&t), f(func) { }
void operator()() const { (object->*f)(); }
private:
T* object;
Func f;
};
template<typename T> callback<T> *make_callback( T& t, void (T::*f) () ) {
return new callback<T>( t, f );
}
// Los tipos de eventos que soportamos:
enum notifications {
NOTIFICATION_ONE,
NOTIFICATION_TWO,
NOTIFICATION_MAX
};
// Nuestro Manejador de Eventos:
class EventManager {
public:
void registerHandler( callbackbase *function, enum notifications notification) {
functions[notification].push_back( function );
}
void notifyHandlers( enum notifications notification ) {
for ( std::list<callbackbase*>::iterator iter = functions[notification].begin(); iter != functions[notification].end(); iter++ ) {
(*(*iter))();
}
}
private:
std::list<callbackbase *> functions[NOTIFICATION_MAX];
};
// Clases de ejemplo
class Class1 {
public:
Class1( const std::string &instance ) : instance( instance ) { };
void function1() { std::cout <<"class1::function1: " <<instance <<std::endl; };
void function2() { std::cout <<"class1::function2: " <<instance <<std::endl; };
private:
std::string instance;
};
class Class2 {
public:
void function1() { std::cout <<"class2::function1" <<std::endl; };
};
class Class3 : public callbackbase {
public:
virtual void operator()() const { std::cout <<"class3::function1" <<std::endl; };
};
//
int main() {
// Clases que van a recibir los eventos:
Class1 class1a("1a");
Class1 class1b("1b");
Class2 class2;
Class3 class3;
// Creamos nuestro manejador de eventos:
EventManager eventManager;
// Creamos al vuelo callbacks a funciones de clases que no heredan de callbackbase:
eventManager.registerHandler( make_callback( class1a, &Class1::function1 ), NOTIFICATION_ONE );
eventManager.registerHandler( make_callback( class1a, &Class1::function2 ), NOTIFICATION_ONE );
eventManager.registerHandler( make_callback( class1b, &Class1::function1 ), NOTIFICATION_ONE );
eventManager.registerHandler( make_callback( class2, &Class2::function1 ), NOTIFICATION_ONE );
// Registramos una clase que hereda callbackbase:
eventManager.registerHandler( &class3, NOTIFICATION_ONE );
// Lanzamos un evento a nuestras funciones:
eventManager.notifyHandlers( NOTIFICATION_ONE );
return 1;
}