【问题标题】: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?当目标指针不是基类的类型时,为什么允许 dynamic_cast 为多态类产生空指针?
【发布时间】:2020-05-08 00:10:18
【问题描述】:

考虑以下程序

#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 类设为多态类。

#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的这种指针转换是允许的?

【问题讨论】:

  • 假设,可能有一个类继承自 A 和 C,因此通过动态转换从 C* 转换为 A* 是有效的 - 因为一般的转换不一定会失败。跨度>

标签: c++ polymorphism c++17 dynamic-cast nullptr


【解决方案1】:

允许dynamic_cast 的这种指针转换的原因是什么?

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

如果转换失败,dynamic_cast 返回nullptr。您需要对此进行检查,然后在需要时进行处理。

【讨论】:

  • 所以无法区分源指针最初等于nullptr和转换不正确的时候不是吗?
  • @VladfromMoscow 为此,您可以在转换前检查源指针。否则是的,你不会知道这是失败还是你刚刚收到一个空指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2012-08-15
  • 2011-03-04
相关资源
最近更新 更多