Проблема не в typeid
. Проблема в том, что typeid
побудит вас написать это:
PolymorphicType *pType = ...;
if(typeid(*pType) == typeid(Derived1))
pType->Func1();
else if(typeid(*pType) == typeid(Derived2))
pType->Func2();
else if(typeid(*pType) == typeid(Derived3))
pType->Func3();
Это то, что мы называем «действительно глупым». Это виртуальный вызов функции, выполненный наименее разумным способом. typeid
может привести к злоупотреблениям при использовании вместо функций dynamic_cast
и virtual
.
Этот пример может показаться надуманным. Ведь очевидно же, что это всего лишь виртуальный звонок. Но плохой код часто вырастает из пути наименьшего сопротивления; все, что нужно, это чтобы один человек сделал typeid() == typeid()
, и зародыш этого кода уже начался. В общем, если вы часто используете typeid
напрямую, велика вероятность, что вы делаете что-то, что можно было бы лучше сделать с помощью других языковых конструкций.
typeid
– это последний метод вывода полиморфного типа.
Все ли случаи использования typeid
неверны? Конечно нет. boost::any
без него было бы невозможно. Что ж, это было бы возможно, но это было бы не безопаснее, чем void*
. typeid
- это то, что делает возможным безопасное стирание типа boost::any
. Есть и другие законные способы его использования.
Но по соотношению количества строк кода к использованию я бы предположил, что это должно быть максимум одна из 10 000 строк кода. Намного меньше, чем это, и вы, вероятно, используете его неправильно.
Медленна ли проверка типов?
В общем, основная причина для вызова typeid
либо в шаблонном коде (как в boost::any
), либо когда вы ожидаете полиморфный тип. Если тип определен статически (т. е. задано имя типа или значение неполиморфного типа), вы можете ожидать, что это будет сделано во время компиляции.
Это полиморфные значения, о которых вы должны беспокоиться. Я видел тест производительности, который показал, что некоторые реализации typeid
фактически обходят иерархию классов, поэтому время, необходимое им для поиска типа, пропорционально количеству классов между реальным типом и заданным типом. Каждая реализация будет отличаться, но это довольно хороший показатель того, что, возможно, вам не следует помещать его в критически важный для производительности код.
person
Nicol Bolas
schedule
03.03.2012
if (typeid(a) == atype) doa(); else if (typeid(a) == btype) dob(); else if (typeid(a) == ctype) doc();
вы можете просто выполнитьa->doafunc();
, и соответствующая виртуальная функция будет вызвана для типа среды выполненияa
. - person Seth Carnegie   schedule 03.03.2012