C++ Event Handling

Related to the Observer design pattern. Inspired from C# event handling.

Event Source

 * 1) pragma once


 * 1) include "eventreceiver.h"
 * 2) include

class Event_source { public: virtual ~Event_source {} void raise(int event_id); void set_receiver(int event_id, Event_receiver *receiver);

private: std::multimap event_receivers; };

// call all event receivers for event_id inline void Event_source::raise(int event_id) { typedef std::multimap::iterator MI;

// find all receivers with event_id std::pair receiver_range = event_receivers.equal_range(event_id);

// invoke them for(MI p = receiver_range.first; p != receiver_range.second; ++p) (p->second)->handle(this, event_id); }

inline void Event_source::set_receiver(int event_id, Event_receiver *receiver) {

event_receivers.insert(           std::pair( event_id, receiver)); }

Event Receiver Interface

 * 1) pragma once

class Event_source;

class Event_receiver { public: virtual void handle(Event_source *source, int event_id) = 0; };

Test

 * 1) include "eventsource.h"
 * 2) include "eventreceiver.h"


 * 1) include

using namespace std;

class Ship : public Event_source { public: typedef enum Event_type_enum { CRASH, SHOOT } Event_type; void crash { raise(CRASH); } void shoot { raise(SHOOT); } };

class Enemy : public Ship { };

class Audio_system : public Event_receiver { public: virtual void handle(Event_source *source, int event_id) { if    (dynamic_cast(source)) cout << "Enemy: "; else if(dynamic_cast (source)) cout << "Ship: "; else cout << "U.F.O.: "; switch(event_id) { case Ship::CRASH: cout << "KABOOM" << endl; break; case Ship::SHOOT: cout << "ZAP"   << endl; break; }   } };

int main { Ship ship; Enemy enemy; Audio_system audio_system;

ship.set_receiver(Ship::CRASH, &audio_system); ship.set_receiver(Ship::SHOOT, &audio_system); enemy.set_receiver(Enemy::CRASH, &audio_system); enemy.set_receiver(Enemy::SHOOT, &audio_system);

ship.shoot; enemy.crash; } Output: Ship: ZAP Enemy: KABOOM