Почему dynamic_cast разрешено давать нулевой указатель для классов polymorphi c, когда целевой указатель не относится к типу базового класса? - PullRequest
2 голосов
/ 22 января 2020

Рассмотрим следующую программу

#include <iostream>
#include <iomanip>

struct A
{
};

struct C
{
};

int main()
{
    C *pc = nullptr;

    A *pa1 = dynamic_cast<A *>( pc );

    std::cout << "pa1 == nullptr is " << std::boolalpha << ( pa1 == nullptr ) << '\n';

    A *pa2 = pc;

    std::cout << "pa2 == nullptr is " << std::boolalpha << ( pa2 == nullptr ) << '\n';
}

Для обоих объявлений указателей, pa1 и pa2, компилятор сообщает об ошибке, что такая инициализация не разрешена.

Например, clang HEAD Компилятор 10.0.0 выдает следующие ошибки:

prog.cc:19:14: error: 'C' is not polymorphic
    A *pa1 = dynamic_cast<A *>( pc );
             ^                  ~~
prog.cc:23:8: error: cannot initialize a variable of type 'A *' with an lvalue of type 'C *'
    A *pa2 = pc;
       ^     ~~
2 errors generated.

Теперь давайте сделаем класс C полиморфным c классом.

#include <iostream>
#include <iomanip>

struct A
{
};

struct C
{
    virtual ~C() = default; 
};


int main()
{
    C *pc = nullptr;

    A *pa1 = dynamic_cast<A *>( pc );

    std::cout << "pa1 == nullptr is " << std::boolalpha << ( pa1 == nullptr ) << '\n';

    A *pa2 = pc;

    std::cout << "pa2 == nullptr is " << std::boolalpha << ( pa2 == nullptr ) << '\n';
}

И только второе объявление выдаст ошибку , dynamic_cast работает.

rog.cc:22:8: error: cannot initialize a variable of type 'A *' with an lvalue of type 'C *'
    A *pa2 = pc;
       ^     ~~
1 error generated.

В чем причина того, что такое преобразование указателей для dynamic_cast разрешено?

1 Ответ

4 голосов
/ 22 января 2020

В чем причина того, что такое преобразование указателей для dynamic_cast разрешено?

Поскольку dynamic_cast выполняется во время выполнения, и уже слишком поздно для выдачи к тому времени ошибка компилятора.

Если преобразование завершится неудачно, dynamic_cast вернет nullptr. Вы должны проверить это, а затем обработать это, если необходимо.

...