Проверка типа объекта в C++: аналог Java's instanceof
Быстрый ответ
if (auto* derivedPtr = dynamic_cast<Derived*>(basePtr)) {
// Отлично, basePtr на самом деле является экземпляром класса Derived.
}
Если basePtr действительно относится к типу Derived, derivedPtr будет содержать валидный указатель. Если это не так, derivedPtr будет равен NULL.

Когда стоит избегать dynamic_cast (и кодировать умно!)
Преувеличенное использование dynamic_cast может указывать на то, что нарушается Принцип подстановки Барбары Лисков. В этом случае следует обратить внимание на виртуальные функции, они предназначены для упрощения и повышения эффективности работы с типами.
Проверка родственных связей на этапе компиляции
Метод std::is_base_of позволяет проверить иерархию наследования на этапе компиляции, без затрат времени выполнения.
Паттерн "Посетитель": удобная стратегия замены
Паттерн "Посетитель" позволяет добавлять новые операции для объектов без изменения их классов и представляет собой эффективную альтернативу dynamic_cast.
Визуализация
Проведем аналогию проверки типов в C++ с помощью dynamic_cast: представим это как паспортный контроль:
Java instanceof:
"Ты житель **JavaLand**?" 🛂🌐
C++ dynamic_cast:
"У тебя есть виза для **CPlusPlusLand**?" 🛂✈️
- Успешное приведение типа (👍) подтверждает валидность объекта.
- Неуспешное приведение типа (👎) возвращает
nullptr.
Сравниваем их, как братьев-близнецов: dynamic_cast & typeid
typeid – это удобный инструмент для работы в паре с dynamic_cast, хоть и ограниченный в своих возможностях. Он полезен при определении точного типа объекта.
#include <typeinfo>
if (typeid(*basePtr) == typeid(Derived)) {
// basePtr это объект класса Derived.
}
Но стоит помнить, что в отличие от dynamic_cast, typeid не способен работать с иерархией классов.
Давайте рассмотрим вопрос производительности: Каждая операция имеет свою цену!
RTTI влияет на производительность, поэтому если она для вас критическая, рассмотрите использование шаблонов или концепций C++20.
Проверки на этапе компиляции с помощью макросов: Все мы не любим затраты времени выполнения, не так ли?
С C++11 можно использовать макросы и метапрограммирование для проверки типов на этапе компиляции.
#define isType(Type, obj) (typeid(obj) == typeid(Type))
Этот макрос применяется для быстрой проверки типов без затрат времени выполнения.
Множественное наследование: Насколько хорошо вы управляетесь со своими типами?
Если вы используете dynamic_cast в совокупности с множественным наследованием, возможно придется пересмотреть дизайн классов или воспользоваться более простыми подходами, например, использованием enum.


