Я бы порекомендовал использовать виртуальную функцию для каждого события, которое выполняет любое событие. Если вам действительно нужно, чтобы обработка событий происходила в центральном месте (если да, то вы уверены, что вам это нужно?), То вы можете использовать шаблон посетителя, чтобы каждое событие имело виртуальную функцию, которая вызывает специфичный для события метод для вашего центральный процессор событий. Таким образом, вы можете определить тип события без каких-либо приведений или идентификаторов типов.
Чтобы ответить на ваш фактический вопрос, если вы хотите остаться с идентификаторами типов и вам не нужна эффективность, вы можете сделать это:
class Event {
public:
int getId() {
std::map<std::string, int>::iterator it = types.find(typeid(*this).name());
if (it == types.end()) {
int newId = types.size();
return types[typeid(*this).name()] = newId;
} else
return it->second;
}
private:
static std::map<std::string, int> types;
};
Это, вероятно, не компилируется, так как я не пробовал, но вы поняли идею. Вы также можете использовать метод type_info.before, чтобы избежать использования строк, но это все равно оставляет поиск карты. Если вы используете хеш-таблицу, то это может быть не так уж и медленно, но все равно не так быстро, как решение, которое вы уже получили.
Также может работать быстрее использование адреса const char *, возвращаемого type_info :: name напрямую в качестве идентификатора, но я не уверен, что есть гарантия, что он всегда возвращает один и тот же адрес для одного и того же типа, хотя разумно надеяться, что так и будет. Это было бы довольно быстро в этом случае. Я не очень рекомендую это решение.
Я думаю, что вы беспокоитесь о своем собственном заявленном решении, что два разных класса событий могут происходить из одного и того же события, например из-за ошибки вырезать и вставить. Чтобы поймать это, вы можете проверить, что Event :: getId никогда не вызывается для объектов с разными динамическими типами, такими как:
#ifdef DEBUG
static type_info myType = typeid(*this);
assert(myType == typeid(*this));
#endif
Обратите внимание, что это будет подтверждено, если вы подклассифицируете событие с идентификатором, но не хотите давать новому дочернему классу отдельный идентификатор типа.