这不能在 C++ 中编译:
class A
{
};
class B : public A
{
};
...
A *a = new B();
B *b = dynamic_cast<B*>(a);
这不能在 C++ 中编译:
class A
{
};
class B : public A
{
};
...
A *a = new B();
B *b = dynamic_cast<B*>(a);
因为dynamic_cast
只能向下转换多态类型,所以标准如此说。
您可以通过向virtual
基类添加析构函数来使您的类具有多态性。事实上,你可能应该无论如何(见脚注)。否则,如果您尝试B
通过A
指针删除对象,您将唤起Undefined Behavior。
class A
{
public:
virtual ~A() {};
};
瞧!
关于在多态类型中需要虚拟析构函数的“规则”有一些例外。
一个这样的例外是当boost::shared_ptr
史蒂夫杰索普在下面的评论中指出的那样使用时。有关何时需要虚拟析构函数的更多信息,请阅读Herb Sutter文章。
正如另一个所说:标准是这样说的。
那么为什么标准会这样说呢?
因为如果类型不是多态的,它可能(或者是?标准专家的问题)是普通类型。对于普通类型,有许多来自 C 向后兼容性的假设。其中之一是该类型仅由开发人员声明的成员+必要的对齐字节组成。所以不能有任何额外的(隐藏的)字段。所以没有办法在 A 保存的内存空间中存储它确实是 B 的信息。
这只有在它是多态的时候才有可能,因为它允许添加这样的隐藏的东西。(在大多数实现中,这是通过 vtable 完成的)。
从 5.2.7(动态演员):
表达式
dynamic_cast<T>(v)
的结果是将表达式 v 转换为类型 T 的结果。[ ... 引用其他情况的多行 ... ]
否则 v 应为指向多态类型 (10.3) 的指针或左值。
从 10.3(虚拟功能)开始:
声明或继承虚函数的类称为多态类。