8

我知道使用dynamic_cast跨类层次结构进行“交叉转换”是合法的。例如,如果我有如下所示的类:

  A   B
   \ /
    C

如果我有一个A*指向 type 对象的指针C,那么我可以使用

A* aPtr = /* ... something that produces a C* ... */
B* bPtr = dynamic_cast<B*>(aPtr);

获取指向我指向的B基础对象的指针。C

我提到这一点的原因是,在我编写上述代码时,编译器可能还没有看到 的定义,C即使它已经看到了Aand B。这意味着编译器可能没有检测到 and 之间的任何类型的连接AB但它仍然必须编译代码,因为这样的类可能C存在并且dynamic_cast在某些情况下成功。

问题是这意味着我可能会意外地交叉转换为错误类型的对象。假设我有如下所示的类:

A   B    D
 \ /   
  C

这里,D是一些随机不相关的类。如果我尝试写这样的东西:

A* aPtr = /* ... get a C* pointer ... */
D* dPtr = dynamic_cast<D*>(aPtr);

那么这dynamic_cast在运行时总是会失败,因为没有办法连接AD. 如果我D因为我打算使用而意外使用B,编译器将不会给我任何迹象表明我有一个毫无意义的演员表。

我的问题是:有什么方法可以让编译器警告我强制转换在运行时总是会失败? 对于可以检测到这一点的任何主要编译器,我都会对语言级解决方案或某些编译器设置感到满意。如果有外部工具,那也没关系;我只想知道是否有可能捕获此类错误。

4

3 回答 3

3

在编译时无法检测到这一点。C可以在尚未编写的动态可加载库中找到引入这种关系的类,编译器无法证明其他情况。

不过可能有一些例外。如果A只有私有构造函数(或私有析构函数),那么编译器可以确定不会有新的子类未被A.

于 2011-03-16T06:15:59.910 回答
0

这就是动态转换的全部含义:它是动态的,即在运行时而不是在编译时检查它。

编译器只检查转换的类是否是多态的。如果类不是多态的,那么在运行时将没有足够的信息来检查转换。

最后,在动态转换之后,程序应该检查接收到的指针是否不为空。如果你转换到一个引用,那么你应该捕获 std::bad_cast。

于 2017-04-04T09:57:40.210 回答
-3

事实是,当您使用时,dynamic_cast即使类彼此不相关,您也可以将任何多态类型指针转换为任何多态类型指针。

如果您想要编译时检查,您需要使用其他强制转换 -static_cast或隐式转换 - 在许多情况下可能不适合某些其他原因。

我们在dynamic_cast需要时使用的解决方案是一个模板函数,dynamic_cast如果获得空指针,它会执行并抛出异常。这当然只是运行时检查,但它相当可靠。

于 2011-03-16T06:15:39.490 回答