24

这不能在 C++ 中编译:

class A
{
};

class B : public A
{
};

...

A *a = new B();
B *b = dynamic_cast<B*>(a);
4

3 回答 3

33

因为dynamic_cast只能向下转换多态类型,所以标准如此说。

您可以通过向virtual基类添加析构函数来使您的类具有多态性。事实上,你可能应该无论如何(见脚注)。否则,如果您尝试B通过A指针删除对象,您将唤起Undefined Behavior

class A
{
public:
  virtual ~A() {};
};

瞧!

脚注

关于在多态类型中需要虚拟析构函数的“规则”有一些例外。
一个这样的例外是当boost::shared_ptr史蒂夫杰索普在下面的评论中指出的那样使用时。有关何时需要虚拟析构函数的更多信息,请阅读Herb Sutter文章。

于 2010-11-19T16:51:21.757 回答
11

正如另一个所说:标准是这样说的。

那么为什么标准会这样说呢?

因为如果类型不是多态的,它可能(或者是?标准专家的问题)是普通类型。对于普通类型,有许多来自 C 向后兼容性的假设。其中之一是该类型仅由开发人员声明的成员+必要的对齐字节组成。所以不能有任何额外的(隐藏的)字段。所以没有办法在 A 保存的内存空间中存储它确实是 B 的信息。

这只有在它是多态的时候才有可能,因为它允许添加这样的隐藏的东西。(在大多数实现中,这是通过 vtable 完成的)。

于 2010-11-19T17:29:12.417 回答
8

从 5.2.7(动态演员):

表达式 dynamic_cast<T>(v)的结果是将表达式 v 转换为类型 T 的结果。

[ ... 引用其他情况的多行 ... ]

否则 v 应为指向多态类型 (10.3) 的指针或左值。

从 10.3(虚拟功能)开始:

声明或继承虚函数的类称为多态类。

于 2010-11-19T16:55:15.123 回答