Система событий на c++

113
19 октября 2021, 21:50

Подскажите оптимальный способ для реализации событий на C++.
Нужно реализовать подписку на события, с возможностью передачи аргументов. Такая система есть в Node JS(https://metanit.com/web/nodejs/2.9.php).

Например, есть объект класса Player, в этом классе содержится функция OnConnected.
К примеру, я хочу установить слушатель на эту функцию: EventManager.subscribe(object, OnConnected, функция-слушатель c аргументами).
При вызове функции OnConnected должна вызываться функция-слушатель с аргументами.

Answer 1

Это скорее сигналы, нежели события. Могу посоветовать boost (сам не использовал тамошние сигналы) или Qt (в ней система сигналов-слотов довольно хорошая, НО имеет достаточно подводных камней и требует метакомпилятор)

Answer 2

Можно реализовать шаблон Observer (при помощи него, в частности, реализована система событий в Java).

Создаем интерфейс для слушателей событий в классе Player:

class IPlayerEventsListener {
protected:
    virtual void onConnected(/*Необходимые аргументы*/) {};
}

С его помощью мы будем регистрировать и слушать события нашего Игрока:

class Player {
public:
    explicit Player() : _listener(nullptr) {}
    void setListener(IPlayerEventsListener* listener) {
        _listener = listener;
    }
    void onConnected() {
        // Логика
        // А теперь сообщаем о данном событии слушателю
        if( _listener != nullptr ) {
            _listener.onConnected(/*Что-то передаем*/);
        }
    }
private:
    IPlayerEventsListener* _listener;
}

Теперь, чтобы начать слушать объекты класса Player надо наследовать и реализовать соответствующий интерфейс "снаружи":

class SomePlayerListener : public IPlayerEventsListener {
public:
    void onConnected(/*Необходимые аргументы*/) override {
        //реагируем на событие, например пишем логи куда надо
    }
}

Регистрируем слушатель в игроке:

// Где-то, на просторах нашего кода
SomePlayerListener playerListener;
Player player;
player.setListener(&playerListener);

Можно реализовать класс посредник EventManager, который будет осуществлять данную операцию:

class EventManager {
public:
    static void subscribe(Player& player /*events provider*/, 
                          IPlayerEventsListener& listener /*subscriber*/) {
        // если надо, то что-то проверяем
        // регистрируем
        player.setListener(&listener);
    }
}
READ ALSO
Как заставить класс узнать про экземпляр другого класса?

Как заставить класс узнать про экземпляр другого класса?

У меня есть класс BinTree, описывающий бинарное дерево поиска:

197
шаблонные классы в разных файлах [дубликат]

шаблонные классы в разных файлах [дубликат]

написал на взгляд ОБСОЛЮТНО рабочий код, но он не работает(

115
Не удается открыть файл включение: No such file or directory QT CREATOR

Не удается открыть файл включение: No such file or directory QT CREATOR

Пишу приложение, использую qt creator в качестве ide, и понадобилось мне использовать SFML, но возникла проблема: вpro файл добавил код для подключения...

214