检查交叉投射是否可行?

时间:2011-03-16 06:09:35

标签: c++ static-analysis dynamic-cast cross-cast

我知道使用dynamic_cast在类层次结构中进行“交叉投射”是合法的。例如,如果我的类看起来像这样:

  A   B
   \ /
    C

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

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

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

我提到这个的原因是,在我编写上面的代码时,编译器可能还没有看到C的定义,即使它看到A和{{1 }}。这意味着编译器可能没有检测到BA之间的任何类型的连接,但它仍然必须编译代码,因为像B这样的类可能会存在,C在某些情况下成功。

问题在于这意味着我可能会意外地交叉转换为错误类型的对象。假设我有类似这样的类:

dynamic_cast

在这里,A B D \ / C 是一些随机无关的类。如果我尝试写这样的东西:

D

然后这个A* aPtr = /* ... get a C* pointer ... */ D* dPtr = dynamic_cast<D*>(aPtr); 将始终在运行时失败,因为没有可能的方法来连接dynamic_castA。如果我意外使用D,因为我打算使用D,编译器将不会给我任何关于我无意义演员的指示。

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

3 个答案:

答案 0 :(得分:3)

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

但可能有一些例外。如果A只有私有构造函数(或私有析构函数),那么编译器可以确定没有新的子类没有被A命名为朋友。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:-3)

真相是当你使用dynamic_cast时,你可以将任何多态类型指针强制转换为任何多态类型指针,即使类彼此无关。

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

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