Рассмотрим следующую программу
#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
разрешено?