“安全”的动态转换?

5

我熟悉如何在C++中进行动态转换,具体操作如下:

myPointer = dynamic_cast<Pointer*>(anotherPointer);

但是如何使这个“安全”的动态转换呢?

4
您所说的“安全”,是指什么? - Dietrich Epp
5
请确认一下myPointer是否非空。 - cbel
3
如果使用不当,一切都可能成为失效点。你试图避免什么样的问题? - Dietrich Epp
4
只有使用引用时,类型转换失败会抛出异常;而使用指针时,类型转换失败则会返回一个空指针。具体取决于你想要什么,如果你不想为每个转换检查非空值,请使用引用。如果你不想捕获异常,请使用指针。 - user1520427
3
请检查指针是否非空,如果您使用的是C++11,请将其与“nullptr”进行比较。 - user1520427
显示剩余15条评论
3个回答

8

dynamic_cast无法将指针强制转换为所需类的完整对象时,会返回空指针以表示失败。 如果使用dynamic_cast进行引用类型转换并且无法进行转换,则抛出bad_cast类型的异常。


1
你意味着使用空值检查或异常处理来解决这个问题,所以感谢你的回答。 - user3308043

0

但是如何将它变成“安全的”动态转换呢?

只要将 dynamic_cast 的参数传递为有效指针(包括NULL),它就是一个安全的动态转换。如果你传递了一个悬挂指针或者是垃圾值,那么调用 dynamic_cast 将不保证安全。事实上,最好的情况是运行时系统抛出异常,你可以处理它。最糟糕的情况是未定义的行为。现在你可以得到一种行为,下次可能会有不同的行为。


1
如果您传递了一个悬空指针,为什么会抛出异常? - Dietrich Epp
这个问题应该在 try/catch 块中处理吗? - user3308043
3
对一个悬空指针进行动态类型转换听起来像是应该有未定义行为。这个指针可能会指向仍然有效的东西。 - dutt
我认为这个答案没有抓住重点。当然,在悬空指针上执行操作是不安全的,我认为OP想知道的是它是否会在错误数据上抛出异常,如果不会,要检查什么。 - user1520427

0

你可能尝试滥用dynamic_cast的大多数方式最终会导致编译器错误(例如,试图将其转换为不在相关多态层次结构中的类型)。

当你实际使用dynamic_cast来询问特定指针是否实际寻址特定派生类型的对象时,也有两种运行时行为:

if (Derived* p = dynamic_cast<Derived*>(p_base))
{
    ...can use p in here...
}
else
    ...p_base doesn't point to an object of Derived type, nor anything further
       derived from Derived...

try
{
    Derived& d = dynamic_cast<Derived&>(*p_base);
    ...use d...
}
catch (std::bad_cast& e)
{
    ...wasn't Derived or further derived class...
}

上述代码只有在 p_basenullptr/0 或确实指向从 Base 派生的对象时才是“安全”的(定义行为),否则将导致未定义行为。

此外,还有一种运行时不安全的方法可以使用 dynamic_cast<>,这会导致未定义行为:

  • 标准 12.7/6:“如果 dynamic_cast 的操作数引用正在构建或销毁的对象,并且操作数的静态类型不是指向构造函数或析构函数自己的类或其基类之一的指针或对象,则 dynamic_cast 的结果是未定义的行为。” 标准提供了一个示例来说明这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接