Как определить фактический тип объекта во время выполнения в 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
имеет по крайней мере одну виртуальную функцию-член. Что и должно быть, раз уж ты манипулируешь типов, производных от него через базовый указатель, поэтому он должен иметь виртуальный деструктор.