Related to the Observer design pattern. Inspired from C# event handling.
#pragma once
#include "eventreceiver.h"
#include <map>
class Event_source {
public:
virtual ~Event_source() {}
void raise(int event_id);
void set_receiver(int event_id, Event_receiver *receiver);
private:
std::multimap<int, Event_receiver *> event_receivers;
};
// call all event receivers for event_id
inline void
Event_source::raise(int event_id) {
typedef std::multimap<int, Event_receiver *>::iterator MI;
// find all receivers with event_id
std::pair<MI, MI> 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<int, Event_receiver *>(
event_id, receiver));
}
#pragma once
class Event_source;
class Event_receiver {
public:
virtual void handle(Event_source *source, int event_id) = 0;
};
#include "eventsource.h"
#include "eventreceiver.h"
#include <iostream>
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<Enemy *>(source)) cout << "Enemy: ";
else if(dynamic_cast<Ship *> (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