为什么当目标指针不是基 class 类型时,dynamic_cast 允许为多态 classes 生成空指针?

Why is the dynamic_cast allowed to yield a null-pointer for polymorphic classes when the destination pointer is not of the type of a base class?

考虑以下程序

#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.

现在让我们把 class C 变成多态的 class。

#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指针转换的原因是什么?

What is the reason of that such a conversion of pointers for the dynamic_cast is allowed?

因为 dynamic_cast 运行s 在 运行 时间,到那时发出编译器错误为时已晚。

如果转换失败,dynamic_cast returns nullptr。您需要检查一下,然后在需要时进行处理。