Проверка типа объекта в C++: аналог Java's instanceof

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

cpp
Скопировать код
if (auto* derivedPtr = dynamic_cast<Derived*>(basePtr)) {
    // Отлично, basePtr на самом деле является экземпляром класса Derived.
}

Если basePtr действительно относится к типу Derived, derivedPtr будет содержать валидный указатель. Если это не так, derivedPtr будет равен NULL.

Кинга Идем в IT: пошаговый план для смены профессии

Когда стоит избегать dynamic_cast (и кодировать умно!)

Преувеличенное использование dynamic_cast может указывать на то, что нарушается Принцип подстановки Барбары Лисков. В этом случае следует обратить внимание на виртуальные функции, они предназначены для упрощения и повышения эффективности работы с типами.

Проверка родственных связей на этапе компиляции

Метод std::is_base_of позволяет проверить иерархию наследования на этапе компиляции, без затрат времени выполнения.

Паттерн "Посетитель": удобная стратегия замены

Паттерн "Посетитель" позволяет добавлять новые операции для объектов без изменения их классов и представляет собой эффективную альтернативу dynamic_cast.

Визуализация

Проведем аналогию проверки типов в C++ с помощью dynamic_cast: представим это как паспортный контроль:

Markdown
Скопировать код
Java instanceof: 
"Ты житель **JavaLand**?" 🛂🌐
cpp
Скопировать код
C++ dynamic_cast:
"У тебя есть виза для **CPlusPlusLand**?" 🛂✈️
  • Успешное приведение типа (👍) подтверждает валидность объекта.
  • Неуспешное приведение типа (👎) возвращает nullptr.

Сравниваем их, как братьев-близнецов: dynamic_cast & typeid

typeid – это удобный инструмент для работы в паре с dynamic_cast, хоть и ограниченный в своих возможностях. Он полезен при определении точного типа объекта.

cpp
Скопировать код
#include <typeinfo>

if (typeid(*basePtr) == typeid(Derived)) {
    // basePtr это объект класса Derived.
}

Но стоит помнить, что в отличие от dynamic_cast, typeid не способен работать с иерархией классов.

Давайте рассмотрим вопрос производительности: Каждая операция имеет свою цену!

RTTI влияет на производительность, поэтому если она для вас критическая, рассмотрите использование шаблонов или концепций C++20.

Проверки на этапе компиляции с помощью макросов: Все мы не любим затраты времени выполнения, не так ли?

С C++11 можно использовать макросы и метапрограммирование для проверки типов на этапе компиляции.

cpp
Скопировать код
#define isType(Type, obj) (typeid(obj) == typeid(Type))

Этот макрос применяется для быстрой проверки типов без затрат времени выполнения.

Множественное наследование: Насколько хорошо вы управляетесь со своими типами?

Если вы используете dynamic_cast в совокупности с множественным наследованием, возможно придется пересмотреть дизайн классов или воспользоваться более простыми подходами, например, использованием enum.

Полезные материалы

  1. Преобразование при помощи dynamic_cast – cppreference.com
  2. Документация IBM по dynamic_cast
  3. Углубленный урок о RTTI от Bo Qian – YouTube
  4. Стандарт C++