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

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

Base* b = new Derived():

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

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

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

Ответы

Ответ 1

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


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

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

Ответ 2

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

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

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

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