dynamic_cast转换失败是正常设计行为:指针版返回nullptr需手动检查,引用版抛std::bad_cast需try/catch;基类必须含虚函数启用rtti,否则行为未定义。

dynamic_cast 转换失败本身不是错误,而是设计上的正常反馈——关键是你没检查它返回的 nullptr 或没捕获 std::bad_cast。
为什么 dynamic_cast 会返回 nullptr 而不直接报错
它本意就是“尝试转换,失败就告诉你”,不是编译器拦你,是运行时发现对象真实类型不匹配。常见触发点包括:
- 实际指向的是基类对象,却想转成某个派生类指针
- 基类没虚函数(比如只有
struct Base {};),dynamic_cast根本不工作,编译失败或静默返回nullptr - 继承关系存在但目标类型不相关(比如从
Animal*转到Car*)
别指望它抛异常来“提醒你出错了”——指针版永远只返回 nullptr,只有引用版才会抛 std::bad_cast。
指针转换必须显式判空,不能跳过
这是最常崩的点:拿到 dynamic_cast 结果后直接解引用,完全没检查是否为 nullptr。
正确写法就三步:
- 用指针接收结果:
Derived* d = dynamic_cast<derived>(base_ptr);</derived> - 立刻判断:
if (d != nullptr) { /* 安全使用 */ } - 别在 else 分支里继续用
d—— 它就是个空指针
漏掉第二步,等于把空指针当有效对象用,崩溃只是时间问题。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
引用转换必须配 try/catch,不能靠 if
引用版不返回 nullptr,失败直接抛 std::bad_cast,所以 if 没用。
写法必须是:
try {
Derived& d = dynamic_cast<derived>(*base_ptr);
d.specificMethod();
} catch (const std::bad_cast&) {
// 处理转换失败,比如记录日志或 fallback 行为
}
</derived>
试图用 if (dynamic_cast<derived>(*base_ptr))</derived> 是语法错误——引用不能用于条件判断。
比处理失败更关键的是:先确认它能不能用
很多“失败”其实源于误用前提:
- 基类必须至少有一个虚函数(哪怕只是
virtual ~Base() = default;),否则 RTTI 不生成,dynamic_cast编译不过或行为未定义 - 不能对
void*、普通结构体、C 风格数组用dynamic_cast—— 它只认多态类的指针/引用 - 转换目标必须在继承体系中真正可达(单继承、多继承都行,但不能跨无关分支)
如果每次转换都失败,优先查基类有没有虚函数,而不是急着加 try/catch。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










