【问题标题】:Legal dynamic_cast合法的dynamic_cast
【发布时间】:2012-12-02 12:04:35
【问题描述】:

我想知道如何解决这个问题。我不明白这个问题在问我什么:

dynamic_cast<Y>(new X)
  • 要合法吗?
  • 可能会成功?

【问题讨论】:

  • 这是做什么用的?
  • 它询问您YX 的哪些类型组合使此代码合法,以及YX 的哪些类型组合使其可能成功。例如,如果YX 的基类并且有一个虚析构函数,...

标签: c++ dynamic-cast


【解决方案1】:

首先,为了合法,Y 必须是指针类型。让我们 将问题改写为dynamic_cast<Y cv_qualifiers*>( new X )。做完这件事就是 如果X 是一个完整的类类型,并且如果X 是一个 多态类型,或者Y 是与X 相同的类型或者是一个基类 X 的类。

如果YX相同,或者是 X。请注意,在这些情况下,dynamic_cast 具有相同的 行为为static_cast,实际上对应于 隐式转换,所以通常只写new X, 没有任何演员。 (有一些特殊情况,演员表 可能是必需的,通常在将结果传递给 void* 参数时。在这种情况下,我宁愿 static_cast,但两者的语义正是 在这种情况下也是如此。)

最后,有一种特殊情况(也会成功):如果 X 是多态类型,Yvoid cv_qualifiers *。在这种情况下,dynamic_cast 确实static_cast有不同的语义,虽然 因为从new X 返回的X* 将具有类型 “指向大多数派生类型的指针”,实际效果 将是相同的(同样,与隐式相同 转换)。

【讨论】:

  • @KerrekSB 好点。这将是您可能需要dynamic_cast 的另一种情况。
  • @BarnabasSzabolcs Y 在这里不能是引用类型,因为我们正在转换一个指针(new 表达式的结果)。 dynamic_cast 可以将指针转换为指针,或将引用转换为引用,但不能将指针转换为引用,反之亦然。
【解决方案2】:

问题应该是:

你对XY的定义有什么看法,这样下面的代码是合法的,而且转换成功了?

那么答案相当直接:X 必须是完整类型,new 表达式才合法。动态转换对于向上转换到非虚基是有效的,所以如果 Y 是一个指向非虚基的指针(可能是 CV 限定的,并且包括指向 X 本身的指针),则转换是有效的 并且成功了。

此外,多态类型(即具有虚函数的类)上的动态强制转换还有其他有效用途。如果X 是多态的,那么Y 可能是void *,或者Y 可能是指向X 继承层次结构中任何其他类的指针。但是,只有当Y 是指向基址的指针时,转换才会成功(不过,这个基址可能是虚拟的!)。

(现在的推理比任意动态强制转换更简单,因为我们已经知道被继承人的动态类型。通常,动态强制转换可以做更复杂的事情。)

【讨论】:

  • @ÖöTiib:是的,相当。谢谢!
  • 这不是真的。如果Y 是一个指向X 基类的指针,那么X 不必是多态的。如果Yvoid*,则转换将成功(但只有在X 是多态时才合法)。
  • @JamesKanze:很有趣。让我仔细检查一下。关于void* 的好点,我真的应该想到这一点。
  • @JamesKanze:谢谢,你是对的。现在答案变得很长。我想知道我是否应该删除它。让我看看我能不能不用太多字就能把它改正。
  • @KerrekSB 真正的答案相当长。 C++ 不是一门简单的语言。 (我们也没有考虑 cv_qualifiers 的作用;例如,Y 可能是 X const*。在这种情况下,由于 new X 的结果不能是 cv 限定的,我认为它们不会发挥作用一个重要的角色,但如果你想完整......)
【解决方案3】:

不知道 Y 和 X 是完全无法回答的。例如,如果 Y 是 int,则非法。否则,如果 Y 是指向多态类的指针,它可能会成功,也可能不会,但肯定没有什么“可能”。最后,这是一个相当严重的内存泄漏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多