Ответ 1
Есть два способа сделать это. Во-первых, вы можете использовать оператор typeid
, который возвращает структуру type_info
, содержащую информацию о типе объекта. Например:
Base* ptr = /* ... */
if (typeid(*ptr) == typeid(DerivedType)) {
/* ... ptr points to a DerivedType ... */
}
Обратите внимание, что здесь вы должны использовать typeid(*ptr)
, а не typeid(ptr)
. Если вы используете typeid(ptr)
, вы вернете объект type_info
для Base*
, так как указатель имеет тип Base*
, независимо от того, на что он указывает.
Важно отметить, что это будет проверять, что точка ptr
находится точно так же, как DerivedType
. Если ptr
указывает на объект типа, полученного из DerivedType
(возможно, EvenMoreDerivedType
), этот код будет работать некорректно.
Альтернативный способ проверки того, указываете ли вы на объект некоторого типа, который является более надежным, заключается в использовании оператора dynamic_cast
. dynamic_cast
выполняет проверенный тип при выполнении во время выполнения, который даст допустимый указатель, если листинг преуспеет и NULL в противном случае. Например:
Base* ptr = /* ... */;
DerivedType* derived = dynamic_cast<DerivedType*>(ptr);
if (derived) {
/* ... points to a DerivedType ... */
}
Это имеет дополнительное преимущество: если ptr
указывает на что-то вроде EvenMoreDerivedType
, приведение будет по-прежнему успешным, потому что EvenMoreDerivedType
наследует от DerivedType
.
В качестве последней мысли вы иногда видите такой код:
Base* ptr = /* ... */
if (DerivedType* derived = dynamic_cast<DerivedType*>(ptr)) {
/* ... points to a DerivedType ... */
}
Это локально - привязывает указатель derived
к телу оператора if
и использует тот факт, что ненулевые значения оцениваются на true
в С++. Я лично считаю, что это легче читать и меньше подвергать ошибкам, но, во что бы то ни стало, идет с тем, что вам просто легче.
Надеюсь, это поможет!