【问题标题】:Is it valid to cast from A* to B* via dynamic_cast when A and B haven't a common ancestor?当 A 和 B 没有共同祖先时,通过 dynamic_cast 从 A* 转换为 B* 是否有效?
【发布时间】:2014-12-10 15:50:12
【问题描述】:

clang 3.5.0g++ 4.9.0 compile the following code fine(带有-std=c++11 -Wall -Wextra -pedantic-errors)和程序输出true

#include <iostream>

struct A
{
    virtual ~A() = default;
};

struct B
{
    virtual ~B() = default;
};

struct C : A, B
{
    virtual ~C() = default;
};

int main()
{
    C c;
    A* ap = &c;
    B* bp = dynamic_cast<B*>(ap);

    std::cout << std::boolalpha << (bp != nullptr) << std::endl;
}

【问题讨论】:

  • 您是否有特殊原因怀疑您看到的行为可能是错误的? (无论哪种方式,这都是一个有效的问题,但它会影响一个好的答案应该关注什么。)
  • @hvd 我几乎可以肯定这是不可能的。我不知道为什么。 :)
  • @hvd 我的意思是我假设程序的输出应该是false,当然,在某些情况下使用dynamic_cast 可能是无效的。
  • 请注意,这不会与 libc++ 链接。
  • 只是添加一些关于这个场景的信息。如果“ap”是指向与 B 的层次结构无关的某个类的指针,则此 dynamic_cast 将返回 null 并且您必须在取消引用之前检查“bp”是否为 NULL。另一种方法是使用带有 dynamic_cast 的引用:B* bp = nullptr; try{ bp = &amp;(dynamic_cast&lt;B&amp;&gt;(*ap)); } catch (...) { std::cout &lt;&lt; "exception" &lt;&lt; std::endl; }

标签: c++ inheritance c++11 casting dynamic-cast


【解决方案1】:

是的。这有时被称为cross-casting,如果它们都是同一个派生对象的基本子对象,就会成功,就像他们在这里一样。

dynamic_cast 是必需的,因为转换需要运行时信息,这两者都是C 对象的一部分。要静态转换,您必须先显式转换为 C*

【讨论】:

  • 谢谢。 Cross-casting 对我来说是一个新名词。
【解决方案2】:

是的,根据 §5.2.7 [expr.dynamic.cast],dynamic_cast&lt;T&gt;(v)(强调我的):

如果 C 是 T 指向或引用的类类型,则运行时检查逻辑执行如下:

— 如果在 v 指向(引用)的最派生对象中,v 指向(引用)一个公共基类 C 对象的子对象,并且如果只有一个 C 类型的对象派生自 v 指向(引用)的子对象,则结果指向(引用)该 C 对象。

否则,如果 v 指向(引用)最派生对象的公共基类子对象,并且 最派生对象的类型有一个 C 类型的基类,它是明确的和公共的,结果指​​向(引用)最派生对象的 C 子对象。

——否则,运行时检查失败。

在您的情况下,v 指的是最派生的对象,它是您的C 的一个实例,但v 的静态类型是指向公共基类A 的指针。引用中提到的C 基类是你的B

【讨论】:

  • 也与可能只是想知道它的人相关:11.2.2 - In the absence of an access-specifier for a base class, public is assumed when the derived class is defined with the class-key struct and private is assumed when the class is defined with the class-key class.
  • @MarcoA.,我想这会很好注意,是的。谢谢。
  • @MarcoA。您的报价与问题或答案有何关联?
  • @Constructor 请注意,如果您使用class 而不是struct,则上述内容将不起作用
  • @Constructor 似乎是 libc++ abi 的问题。 Here's a related post.
猜你喜欢
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 2011-03-03
  • 2014-03-29
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多