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

Допустим, у нас есть иерархия классов. Внизу у нас есть 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: я говорю о независимом от компилятора решении


person user1079475    schedule 09.04.2013    source источник
comment
Это возможно, как объясняется в ответе, но это почти всегда неправильно. Чего вы здесь пытаетесь достичь?   -  person n. 1.8e9-where's-my-share m.    schedule 09.04.2013
comment
Ничего особенного, это просто для спора :)   -  person user1079475    schedule 09.04.2013
comment
Версия, более ориентированная на приложения: stackoverflow.com/questions/351845/ || Более общая версия, в которой не упоминается наследование: stackoverflow.com/questions/11310898/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 18.06.2015


Ответы (2)


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


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

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

person Cheers and hth. - Alf    schedule 09.04.2013
comment
Это хорошая идея, чтобы деструктор был хотя бы одним виртуальным методом. - person Roman Saveljev; 09.04.2013

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

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

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

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

person Angew is no longer proud of SO    schedule 09.04.2013
comment
Но дело в том, что я не хочу изменять код каждый раз, когда добавляю новый класс. - person user1079475; 09.04.2013