为何dynamic_cast要求基类拥有virtual析构函数?
关于dynamic_cast报错与多态类类型的疑问
代码示例
struct Base { Base() {} ~Base() {} }; struct Derived: public Base { Derived() {} ~Derived() {} }; struct AnotherClass: public Base { AnotherClass() {} ~AnotherClass() {} }; int main() { Derived* d = new Derived(); Base* base = d; AnotherClass* ac = dynamic_cast<AnotherClass*> (base); }
运行错误
the operand of a runtime
dynamic_castmust have a polymorphic class type.
将Base类的析构函数设为virtual后问题得以解决,但有两个疑问:
- 为何此处需要基类拥有virtual析构函数,base才会被视为polymorphic class type?
- 既然Derived和AnotherClass继承自Base,它们难道不已经是polymorphic class type吗?
问题解答
首先明确C++里多态类类型(polymorphic class type)的定义:一个类只要包含至少一个虚函数(包括虚析构函数),它就是多态类。
回到你的代码:
- 原始的Base类没有任何虚函数,所以它不是多态类。哪怕Derived和AnotherClass继承自它,这两个子类本身也没有自己的虚函数,所以它们同样不是多态类。
dynamic_cast做运行时类型转换的前提是:操作数的静态类型必须是多态类。因为运行时类型识别(RTTI)依赖虚函数表(vtable)来实现——每个多态类都会生成虚函数表,里面存储了类的类型信息,dynamic_cast就是通过这个表来判断实际类型是否匹配的。
为什么把Base的析构函数设为virtual就解决了?
因为一旦Base有了虚析构函数,它就变成了多态类。同时,子类会继承这个虚析构函数(哪怕子类自己没显式声明),所以Derived和AnotherClass也自动成为多态类了。这时候base指针的静态类型是Base(多态类),满足dynamic_cast的运行时转换要求,就能正常执行类型检查了。
补充一点:其实不一定非要用虚析构函数,给Base加任意一个虚成员函数(比如虚的void foo())也能解决这个问题。不过给基类加虚析构函数是更规范的做法——避免通过基类指针删除子类对象时出现内存泄漏。
内容的提问来源于stack exchange,提问作者Shishir Jessu
相关产品推荐
相关产品推荐

