Я пришел сюда почти с этим вопросом.Проблема в основном в том, что C ++ не позволяет функции типа handle (ExplosionEvent *e)
принимать аргумент e
со статическим типом Event *
, даже если динамический тип e
равен ExplosionEvent *
.Это было бы неплохо, но я не совсем уверен, что еще нужно изменить в языке.
Шаблон Visitor - самое чистое решение, которое я могу придумать.Недостатки в том, что он многословен и не может быть дешевле dynamic_cast<>
.
Main.hpp:
#include <iostream>
class Event;
class Handler;
#include "Event.hpp"
#include "Handler.hpp"
Event.hpp:
#ifndef EVENT_H
#define EVENT_H
class Event
{
public:
virtual void accept (Handler *handler) { }
};
class ExplosionEvent : public Event
{
void accept (Handler *handler);
};
#endif // !EVENT_H
Event.cpp:
#include "Main.hpp"
void
ExplosionEvent::accept (Handler *handler)
{
handler->handleExplosion (this);
}
Handler.hpp:
#ifndef HANDLER_H
#define HANDLER_H
class Handler
{
public:
void handle (Event *event) { event->accept (this); }
virtual void handleExplosion (ExplosionEvent *explosionEvent) { }
};
class ExplosionHandler : public Handler
{
void handleExplosion (ExplosionEvent *explosionEvent);
};
#endif // !HANDLER_H
Handler.cpp:
#include "Main.hpp"
void
ExplosionHandler::handleExplosion (ExplosionEvent *explosionEvent)
{
std::cout << "BOOM!" << std::endl;
}
Main.cpp:
#include "Main.hpp"
int
main (int argc, char *args)
{
Event *event = new ExplosionEvent;
Handler *handler = new ExplosionHandler;
handler->handle (event);
}
Скомпилируйте и запустите:
$ g++ -o boom *.cpp
$ ./boom
BOOM!
$