Каковы принципы системы событий в C ++? - PullRequest
3 голосов
/ 31 августа 2010

Прежде всего, я знаю, что есть отличные реализации (Qt, Boost, cpp-event и т. Д.), Но я задаю вопрос, потому что хочу знать, как это работает!

Если я правильно понимаю, «система событий» использует шаблон Observer: некоторые объекты наблюдают, ожидают, чтобы что-то произошло ... а некоторые другие посылают сигналы. Хорошо.

Итак, допустим, у меня есть класс наблюдателей, с такими вещами:

void Observer::getNotified() 
{
    // Do stuff
}

Мой вопрос: как динамически управлять тем, что нужно делать? Я видел много людей, которые специально говорили не использовать указатели на функции. Для моей текущей потребности я могу сделать оператор switch, тип enum и выбрать другое поведение, но это не очень удовлетворительно. Итак, если это не указатели на функции, как это делается?

Ответы [ 2 ]

4 голосов
/ 31 августа 2010

Существует множество различных реализаций (независимо от языка), но абстрактная идея такова:

  1. имеет идентификатор типа события, чтобы знать, какие события были запущены наблюдаемым объектом (этоможет быть любым, что работает);
  2. иметь список наблюдателей (или нескольких, по одному по типу события?), зарегистрированных в зарегистрированных объектах - что предполагает, что наблюдатели являются функторами (указатель на функцию или объект, который действует как функция) или являются объектами с известным интерфейсом (с виртуальным методом вызова вызванного ионного события);
  3. когда происходит событие (вызывая функцию для наблюдаемого объекта), мы просто просматриваем список зарегистрированных наблюдателей.для типа события и передачи информации о событии (идентификатор плюс, возможно, данные) наблюдаемому для обработки;

Вот упрощенная реализация:

enum EventType
{
   Event_A,
   Event_B,
};

class Observer // for this example i'll suppose observer inherits this class
{
    virtual void catchEvent( EventType e ) = 0; // for sake of the example I just need the event type, not the data, but it's often required

    virtual ~Observer(){}; // virtual base classes require this to work fine.
};

class Observed
{
      typedef std::vector<Observer*> ObserverList; 
      typedef std::map< EventType, ObserverList > ObserversTable;
      ObserversTable m_observers; // we have observers for each event type

public:

     void addObserver( Observer& observer, EventType eType ) 
     { m_observers[ eType ].push_back( observer ); } // this is simplist, to say the least...

     void sendEvent( EventType event ) // here we send the event, it will be catched by observers
     { // note : often this type of system is "buffered", but here we will process it immediatly as it's a simple example

        ObserverList& observers = m_observers[ event ];  
        for ( ObserverList::iterator it = observers.begin(); it != observers.end(); ++it )
        {
              Observer* observer = *it;
              observer->catchEvent( event ); // here an observer receive the event
        }

     }
};

Это действительно базоваяпример, но это может помочь вам понять идею.

1 голос
/ 31 августа 2010

См. Это скорее отличная статья от Пита Гудлиффа, в которой используются различные методы в зависимости от типа события, о котором идет уведомление.

Если вам нужно выбрать действия в рамках одного типа события, обычно ваш код выбирается в зависимости от данных, передаваемых в уведомлении.

...