你可以合法地dynamic_cast到多态类的非多态基类

时间:2017-06-02 13:45:46

标签: c++ casting polymorphism

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>));

无法编译,声明“源类型不是多态的”。我觉得这是一个线索,但是找到属于当前指针所在的类的非多态基类似乎仍然是一个延伸(该句子是否有意义?)。

1 个答案:

答案 0 :(得分:13)

是的,你可以。

正如§5.2.7/ 5中关于表达式dynamic_cast<T>(v)的C ++标准所说:

  

如果T是“指向 cv1 B的指针”并且v具有“指向 cv2的指针 {{1} “这样的话   DB的基类,结果是指向唯一D的指针   B指向的D对象的子对象。

也给出了一个例子:

v

正如您所看到的,多态类显然不是标准允许的struct B { }; struct D : B { }; void foo(D* dp) { B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp; } 的唯一用例。

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

  

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