Как определить фактический тип объекта во время выполнения в C++;

допустим, у нас есть иерархия классов. Внизу у нас есть основание,а вверху выведено. Как определить класс объекта, даже если он преобразуется в указатель базового класса.

Base* b = new Derived():

typeid(b).name(); // i want this to tell me that this is actually derived not base object

есть ли другой способ, кроме ручной реализации строкового поля или такой и виртуальной функции get?

PS: Я говорю о независимом от компилятора решении

2 ответов


убедитесь, что базовый класс имеет хотя бы один виртуальный метод, включают в себя <typeinfo> и используйте свой текущий код только с дополнительным разыменованием,typeid(*b).name().


попутно отметим, что a typeid вызов-это единственное место в C++, где вы можете разыменовать nullpointer с четко определенным поведением, что означает, что он может вызвать исключение:

C++11 §5.2.8 / 2:
"Если выражение glvalue получено путем применения унарного * оператор к указатель и указатель-это нулевое значение указателя (4.10),typeid выражение выдает std::bad_typeid исключения (18.7.3)."


если все вы хотите сделать, это найти, если b на самом деле указывает на Derived, просто использовать dynamic_cast():

if (dynamic_cast<Derived*>(b)) { ... }

dynamic_cast возвращает указатель null, если тип времени выполнения объекта, на который указывает b не Derived (или класс, производный от Derived). В отличие от name() член std::type_info, это инвариант компилятора.

это работает только если Base имеет по крайней мере одну виртуальную функцию-член. Что и должно быть, раз уж ты манипулируешь типов, производных от него через базовый указатель, поэтому он должен иметь виртуальный деструктор.