dynamic_cast失败时对指针返回nullptr,对引用抛出std::bad_cast异常;仅适用于多态类型,基类析构函数须为虚函数,RTTI禁用时行为退化或编译失败。
对指针使用 dynamic_cast,转换失败时**返回 nullptr**;对引用使用则**抛出 std::bad_cast 异常**。这是最根本的分水岭,不区分用法直接判断返回值会踩坑。
常见错误现象:if (ptr == nullptr) 检查对引用类型无效,编译都过不去;而忘了检查指针是否为空,直接解引用就会崩溃。
error: cannot dynamic_cast ... (source type is not polymorphic)
dynamic_cast 行为未定义(尤其涉及继承链中间类时)Base* 转 con
st Derived* 合法,反过来不行)优先用指针 + 空指针检查,比 try/catch 更轻量、更符合 C++ 惯例。引用场景较少,通常出现在明确预期成功、失败即逻辑错误的场合。
实操建议:
Derived* d = dynamic_cast(base_ptr); if (d) { /* 安全使用 d */ }
noexcept(false) 时使用,例如:try {
Derived& d = dynamic_cast(base_ref);
} catch (const std::bad_cast&) {
// 处理错误分支
} if (dynamic_cast(p)) { ... } 这种“一次调用两次转换”的写法——编译器未必优化掉第二次 cast,且可读性差如果编译时加了 -fno-rtti(GCC/Clang)或 /GR-(MSVC),dynamic_cast 对指针会退化为 static_cast(不检查类型,静默失败),对引用则直接编译失败。
这意味着:程序可能在 RTTI 关闭后看似运行正常,实则类型检查完全失效,隐患极深。
__GXX_RTTI 是否定义;MSVC 下看 _CPPRTTI
dynamic_cast 时,所有模块必须用相同 RTTI 设置链接,否则行为不可预测switch)替代运行时类型判断最常见原因是对象内存布局不匹配——比如通过 malloc 分配、未调用构造函数,或对象已被析构但指针仍被使用。
另一个隐蔽原因是多重继承下的指针偏移问题:若 Base* 实际指向的是派生类中某个非首字段的基类子对象,而该基类不是虚继承,dynamic_cast 可能无法正确调整地址。
placement new 未完成初始化的对象做 dynamic_cast
this 做 dynamic_cast,此时 RTTI 信息可能已部分销毁dynamic_cast 的源指针指向的是完整对象的起始地址(即原始 new 返回值)C++ 的 dynamic_cast 不是万能钥匙,它依赖完整的对象生命周期、正确的继承定义和开启的 RTTI 支持。最容易被忽略的是:空指针检查只适用于指针,而引用的异常路径往往在测试中被绕过,上线后才暴露。