В c ++ 11, dynamic_cast возвращает nullptr или 0?

c++11 dynamic-cast nullptr

5513 просмотра

2 ответа

Я хочу проверить результат dynamic_cast. В c ++ 11 (или c ++ 0x, для компиляторов, которые поддерживают nullptr), я должен сравнить с nullptr или 0?

Имеет ли это значение, и если да, то почему?

Зависит ли результат от компилятора?

Автор: Patrick Источник Размещён: 12.11.2019 09:24

Ответы (2)


11 плюса

Решение

И константа nullptr(которая имеет тип nullptr_t), и константа 0неявно преобразуются в нулевое значение любого типа указателя. Таким образом, сравнение с любым из них будет работать и технически нормально. Кстати, это означает, что не dynamic_castвозвращает ни один, он возвращает нулевое значение для определенного типа указателя.

Вероятно, лучше использовать привычку nullptr, чем использовать 0. Насколько я знаю, это действительно необходимо только для правильного разрешения перегрузки (например, одна перегрузка принимает, intа другая - char*). Для последовательности избегание 0будет лучшим.

Что я подразумеваю под «нулевым значением типа указателя»?

Рассмотрим переменную char * ptr. Это тип (неудивительно) char *. Но тип nullptrэто особый тип nullptr_t. Поэтому, когда мы пишем что-то вроде ptr = nullptr, должны произойти некоторые технические вещи

  1. nullptrдолжен быть неявно преобразован в char *.
  2. Результат этого преобразования устанавливается как новое значение ptr.

Нулевое значение для char *является результатом преобразования nullptrв char *. Концептуально это все еще nullptr, но с другим типом ( char *). Это пустое значение отличается от значения Нуля int *или string *или любого другого типа указателя. Мы склонны считать эти нулевые значения просто nullptr(или 0), но каждое из них действительно является отличным значением от другого типа. (Кстати, такое же преобразование происходит для сравнения с использованием ==).

Хотя это может звучать как придирчивые детали, это очень важно в разрешении перегрузки:

void foo(char * ptr) { ... }
void foo(int i) { ... }
void foo(nullptr_t ptr) { ... }

int main()
{
    foo(0); // Calls void foo(int), since 0 is an int
    foo(nullptr); // Calls void foo(nullptr_t), since nullptr is a nullptr_t
    foo(new char('c')); // Calls void foo(char *), since new char('c') is a char*
}

или при назначении несвязанных нулевых значений:

char * c_ptr = nullptr; // Okay
int * i_ptr1 = nullptr; // Okay
int * i_ptr2 = c_ptr;   // COMPILER ERROR HERE
Автор: Ken Wayne VanderLinde Размещён: 16.05.2013 03:10

5 плюса

Оцените результат в логическом контексте:

Base * p = get();

if (Derived * q = dynamic_cast<Derived *>(p))
{
    q->derived_method();
}
else
{
    // *p isn't of type Derived
}

(Это работает в любой версии C ++.)

Автор: Kerrek SB Размещён: 16.05.2013 03:09
Вопросы из категории :
32x32