Этот код показывает, как обрабатывать объект, унаследованный от общего родителя, и dynamic_cast
- от производного.
Есть один базовый интерфейс: event
Есть три типа событий: event_one
, event_two
и event_no
. Их топология следующая:
event_two -> event_one -> event
Итак, event_two
наследуется от event_one
, которое наследуется от event
. И есть event_no
(«нет», потому что он не будет обработан), который наследуется напрямую от event
.
event_no -> event
Мы создаем обработчик событий и передаем все производные к нему.
Ключевая часть - if (dynamic_cast<event_one *>(ievent))
в handler_one::handle_event
, если нет преобразования времени выполнения в производный класс, это вернет нулевой указатель, поэтому вы знаете, что не можете справиться с ним . В противном случае он вернет нужный производный класс. У вас должна быть цепочка производных классов, наиболее производные в первую очередь, для правильной обработки всех случаев.
Я создал два обработчика, один частичный (handler_one
), который обрабатывает события двух типов: event_one
и event_two
(event_two
отсутствует в if
, но, поскольку это event_one
, он будет обработан и вызвана правильная функция; если вы не определяете функцию guid
, в производном, то в event_one
будет называться); и второй (handler_two
), который обрабатывает их все.
Что касается очередей, вы можете хранить event
указателей и забыть о производных классах.
EDIT:
Теперь управляется шаблонами. Нет if
или switch
. Вы можете добавить другие типы событий, специализирующиеся на шаблоне элемента.
Вывод программы:
manuel@desktop:~/projects$ g++ -Wall main.cc -o main -std=c++11 && ./main
Handler 1
Event guid: abcd (id=1)
Event guid: abcd with some custom stuff (id=2)
Event no guid: ugh! this is unhandled (id=-1)
End
Программа:
//
#include <typeindex>
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <functional>
class event
{
public:
event () : _id (0) {}
virtual ~event () {}
virtual int id () { return _id; }
protected:
int _id;
};
class event_one : public event
{
public:
event_one () : _guid ("abcd") { _id = 1; }
~event_one () {}
virtual std::string guid () { return _guid; }
protected:
std::string _guid;
};
class event_two : public event_one
{
public:
event_two () { _id = 2; }
~event_two () {}
virtual std::string guid () { return _guid + " with some custom stuff"; }
protected:
};
class event_no : public event
{
public:
event_no () : _guid ("ugh!") { _id = -1; }
~event_no () {}
virtual std::string guid_no () { return _guid + " this is unhandled"; }
protected:
std::string _guid;
};
class handler_one
{
public:
template<typename Event>
int handle_event (Event * ievent);
};
template<typename Event>
int handler_one::handle_event (Event * ievent) {
std::cout << "Event guid: " << ievent->guid()
<< " (id=" << ievent->id() << ")" << std::endl;
return 0;
}
template<>
int handler_one::handle_event<event_no> (event_no * ievent) {
std::cout << "Event no guid: " << ievent->guid_no()
<< " (id=" << ievent->id() << ")" << std::endl;
return 0;
}
int main (void)
{
event_one eo;
event_two et;
event_no en;
handler_one ho;
std::cout << "Handler 1" << std::endl;
ho.handle_event (&eo);
ho.handle_event (&et);
ho.handle_event (&en);
std::cout << "End" << std::endl;
return 0;
}