【问题标题】:Can you legally dynamic_cast to non-polymorphic base class of a polymorphic class你能合法地将dynamic_cast转换为多态类的非多态基类吗
【发布时间】:2017-11-03 22:56:45
【问题描述】:

this answer,出现了以下场景:

#include <cassert>

struct A {};

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

struct AA{};
template <class T>
struct C : A, T {};

int main()
{
  B * b = new C<B>;
  AA * aa = new C<AA>;
  assert(dynamic_cast<A*>(b));
  assert(dynamic_cast<A*>(aa)); //this line doesn't compile, as expected
}

在 g++ 4.8.4 (Ubuntu) 上,它编译并且断言通过。我的问题是,这真的合法吗?我觉得你根本不应该能够 dynamic_cast 到非多态类,但我坦率地承认我不是这里发生的事情的专家。

当我尝试相反的方向时:

dynamic_cast<B*>((A*)(new C<B>));

它无法编译,说明“源类型不是多态的”。我觉得这是一条线索,但要找到属于当前指针所基于的类的非多态基类似乎仍然很困难(那句话有意义吗?)。

【问题讨论】:

  • 按承诺投票。
  • @Bathsheba 有点令人沮丧的是,我一直在写这个问题,所以给我一个警告,标题似乎很主观,这个问题可能会被关闭:S:P
  • 奇怪不是吗?然而,如此多的垃圾从网上溜走。
  • @SirGuy 也许“你”是一个触发词?

标签: c++ casting polymorphism


【解决方案1】:

是的,你可以。

正如 C++ 标准在第 5.2.7/5 节中所说的 dynamic_cast&lt;T&gt;(v) 表达式:

如果T 是“指向cv1 B 的指针”并且v 的类型是“指向cv2 D 的指针”,那么 BD 的基类,结果是指向唯一B 的指针 v 指向的 D 对象的子对象。

也举了一个例子:

struct B { };
struct D : B { };
void foo(D* dp) {
  B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
}

如您所见,多态类显然不是标准允许的dynamic_cast 的唯一用例。

顺便说一句,cppreference explains it 用不太标准的语言:

如果 new_type 是指向 Base 的指针或引用,则 expression 是对 Derived 的指针或引用,其中 Base 是 Derived 的唯一、可访问的基类,结果是指针或 引用派生对象中的基类子对象 由表达式指出或标识。 (注意:隐式转换和 static_cast 也可以执行这种转换。)

【讨论】:

  • 没有理由这不会起作用,因为根据定义,任何知道源类型的编译器都必须知道它以目标类型为基础。
  • @underscore_d:当然。尽管如此,看到用于此的 dynamic_cast 应该会引起注意,并且可能表示代码中存在逻辑错误。
  • 在我的示例中,dynamic_cast 被赋予了一个指向 B 的指针,然后必须找到派生类 C&lt;B&gt;,然后找到 its 基类 Adynamic_cast 工作。
  • 查看标准草案,§5.2.7/8.1 似乎是我正在寻找的段落,而不是 /5。不同之处在于,由于输入是多态的,因此会考虑最派生的类型(在我的示例中为C&lt;B&gt;)并扫描其基类以查找匹配项。
猜你喜欢
  • 2019-02-09
  • 1970-01-01
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多