Допустим, у нас есть иерархия классов. Внизу у нас есть База, а вверху Производная.
Как определить класс объекта, даже если он преобразован в указатель базового класса.
Base* b = new Derived():
typeid(b).name(); // i want this to tell me that this is actually derived not base object
Есть ли способ, кроме ручной реализации строкового поля или такой и виртуальной функции get?
PS: я говорю о компилятор-независимом решении
убедитесь, что в базовом классе есть хотя бы один виртуальный метод, включите <typeinfo>
и использовать ваш текущий код просто с помощью дополнительной разыменования, typeid(*b).name()
,
мимоходом, обратите внимание, что typeid
call — это единственное место в C ++, где вы можете разыменовать нулевой указатель с четко определенным поведением, что подразумевает, что он может вызвать исключение:
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
возвращает нулевой указатель, если фактический тип времени выполнения объекта, на который указывает b
не является Derived
(или класс, полученный из Derived
). в отличие от name()
член std::type_info
это инвариант компилятора.
Обратите внимание, что это работает только если Base
имеет по крайней мере один виртуальный член функции. Как бы то ни было, так как вы управляете типами, производными от него, через базовый указатель, поэтому у него должен быть виртуальный деструктор.