C ++ Хранение переменных и наследования - PullRequest
3 голосов
/ 01 июня 2010

Вот моя ситуация:

У меня есть система, управляемая событиями, где все мои обработчики являются производными от класса IHandler и реализуют метод onEvent(const Event &event). Теперь Event является базовым классом для всех событий и содержит только перечислимый тип события. Все фактические события являются производными от него, включая событие EventKey, которое имеет 2 поля: (uchar) keyCode и (bool) isDown.

Вот интересная часть: я генерирую событие EventKey, используя следующий синтаксис:

Event evt = EventKey(15, true);

и я отправляю его обработчикам:

EventDispatch::sendEvent(evt); // void EventDispatch::sendEvent(const Event &event);

(EventDispatch содержит связанный список IHandlers и вызывает их метод onEvent(const Event &event) с параметром, содержащим отправленное событие.

Теперь актуальный вопрос:

Скажем, я хочу, чтобы мои обработчики опрашивали события в очереди типа Event, как мне это сделать?

  • Динамические указатели с подсчетом ссылок звучат как слишком большое решение.

  • Делать копии сложнее, чем кажется, так как я получаю только ссылку на базовый тип, поэтому каждый раз, когда мне нужно будет проверить тип события, увеличить значение до EventKey, а затем сделать Копировать для хранения в очереди. Звучит как единственное решение - но неприятно, поскольку мне нужно было бы знать каждый тип события и проверять это для каждого полученного события - звучит как плохой план.

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

Как вы думаете, было бы хорошим решением для этого дизайна?

Ответы [ 3 ]

4 голосов
/ 01 июня 2010

Хорошо, во-первых, эта строка не делает то, что вы думаете:

Event evt = EventKey(15, true);

Это создает временный объект EventKey, разделяет его на базовый класс Event , затем вызывает конструктор копирования Event. Все фактические данные, хранящиеся в классе EventKey, будут потеряны. Если вам нужен полиморфизм, вы хотите использовать либо динамические объекты, либо ссылки.

Что касается вашего фактического вопроса, я бы порекомендовал вам перепроектировать и иметь отдельные очереди (и, следовательно, отдельные обработчики) для каждого типа событий ... onEventA, onEventB и т. Д.

1 голос
/ 01 июня 2010

Вам на самом деле не нужен подсчет ссылок, если вы не поделитесь своими объектами событий. Если у вас есть только один владелец в любой момент времени - в вашем случае это обычно будет очередь событий - тогда вам просто нужно использовать соответствующий контейнер.

Если ваша реализация уже частично реализовала C ++ 0x (например, последние версии g ++ или VC ++ 2010), тогда вы можете просто использовать std::queue<std::unique_ptr<Event>>. Если std::unique_ptr недоступен, вы можете использовать boost::ptr_deque или другой подходящий контейнер из библиотеки Boost Pointer Container .

1 голос
/ 01 июня 2010

Мнение: выберите опцию подсчета ссылок. Используйте boost :: shareed_ptr и boost :: dynamic_pointer_cast для определения фактического типа.

...