Помещение виртуальных функций в структуру

0

Моя цель - написать систему для обработки игровых событий, которые могут быть вызваны каким-то событием, например, игрок, который убивает что-то или получает предмет или что у вас есть. Для этого мне нужно иметь виртуальную функцию, которая выполняется при срабатывании события. Здесь суть того, что я хочу сделать (я знаю, что он не работает в этом текущем состоянии, но лучше всего я могу объяснить, какова моя цель):

class EventManager
{
    public:
        typedef struct
        {
            virtual void run();
            bool triggered;
            std::string name;
        } Event;

        void newEvent(std::string eventName)
        {
            Event newEvent;
            newEvent.name = eventName;
            newEvent.triggered = false;
            eventStack.push_back(newEvent);
        }

        void triggerEvent(std::string eventName)
        {
            std::vector<Event>::iterator itr;

            for(itr = eventStack.begin(); itr != eventStack.end(); itr++)
            {
                if(itr->name == eventName) itr->triggered = true;
            }
        }

        std::vector<Event> eventStack;
};

int main()
{
    EventManager* myEventManager = 0;
    myEventManager = new EventManager();

    myEventManager->newEvent("Event1");
    myEventManager->eventStack.back()::run()
    {
        std::cout << "Event1 has been triggered";
    }

    std::vector<EventManager::Event>::iterator itr;

    for(itr = myEventManager->eventStack.begin(); itr != myEventManager->eventStack.end(); itr++)
    {
        if(itr->triggered)
        {
            itr->run();
            itr->triggered = false;
        }
    }

    return 0;
}

Поэтому в основном мой вопрос: как я могу позволить пользователю моей библиотеки определять, что происходит, когда событие запускается без необходимости писать класс или что-то для каждого события?

Теги:
class
struct
event-handling
virtual

1 ответ

1
Лучший ответ

Рассмотрите это: что такое событие? Событие (С точки зрения его реализации) - это только список обработчиков (обратных вызовов).

То, что вы назвали Event, действительно является классом, который представляет обработчик событий, а ваш EventManager - это событие.

Решение вашей проблемы очень просто: используйте ссылки на функции (указатели функций, lambdas, функторы) для хранения набора обработчиков. Например:

template<typename... ARGS>
struct event
{
   typedef void(*)(ARGS...) handler_type;


   void add_handler(handler_type handler)
   {
        handlers.push_back(handler);
   }

   void raise_event(ARGS args...)
   {
        for(handler_type handler : handlers)
            handler(args...);
   }

private:
    std::vector<handler_type> handlers;
};


void on_foo(int a,int b) { std::cout << "on foo!!! (" << a << "," << b << ")" << std::end; }


int main()
{
    event<int,int> foo;

    foo.add_handler(on_foo);

    foo.raise_event(0,0);
}

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

  • 0
    Отличный ответ! Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню