I’m trying to make a simple event dispatcher system. To put it simply, I have event classes that all derive a IEvent interface. I also have an EventManager class with a couple of methods:
void addListener( int eventID, std::function<void( IEvent *event )> callback );
void dispatchEvent( int eventID, IEvent *event );
The EventManager has a map of vectors:
std::map<int, std::vector<std::function<void( IEvent * )> > > m_events;
Any object can then register via the addListener method, giving it a callback, and it will be notified whenever someone calls dispatchEvent with the same event type:
// add an event listener
EventManager::addListener(Event_MouseMove, std::bind(&Obj::callback, this, std::placeholders::_1));
// the callback method
void Obj::callback( IEvent *e )
{
// here I need to cast e to a MouseEvent *
// I want to get rid of this.
MouseEvent *me = (MouseEvent *)e;
}
When calling dispatchEvent, the caller must pass an IEvent derived class, MouseEvent for example:
// dispatching an Event
EventManager::dispatchEvent(Event_MouseMove, new MouseEvent());
My problem has to do with the callback method.
Say you want to listen for a MouseEvent, the object would have a method like such:
void eventHandler( MouseEvent *event );
The problem is that the callback can not be passed to the addListener method as it is expecting an IEvent * and not a MouseEvent *. To make it work, I just use IEvent types and then the event handler method must cast that IEvent * to the derived type it is expecting; in this case a MouseEvent *.
How can I make it that the addListener method take a pointer to a method that will receive any IEvent derived class ?
As an example:
// add an event listener
EventManager::addListener(Event_MouseMove, std::bind(&Obj::callback, this, std::placeholders::_1));
// the callback method
void Obj::callback( MouseEvent *e ) { ... }
// dispatching an Event
EventManager::dispatchEvent(Event_MouseMove, new MouseEvent());
I don’t think that’s possible, without changing the function parameter of addListener() to having a MouseEvent* parameter (or one derived from MouseEvent) instead of an IEvent* parameter.
If you have eventHandlers that take pointers to other classes (derived from IEvent) as a parameter, you’d thus need a separate addListener() function for each of these, which probably isn’t what you want.
Simply passing an IEvent* and then casting it to the appropriate type in the eventHandler (as you’re currently doing) is probably the way to go.
As an example, Qt actually does something something similar for its eventFilters: http://qt-project.org/doc/qt-4.8/eventsandfilters.html