dynamic_cast是C++中唯一支持运行时类型验证的安全向下转型操作符,依赖虚函数表和RTTI信息确认实际对象类型;必须作用于含虚函数的多态类型,指针转换失败返回nullptr,引用转换失败抛std::bad_cast异常。

dynamic_cast 是唯一安全的向下转型方式
在 C++ 中,dynamic_cast 是唯一能在运行时验证类型合法性的向下转型操作符。它不靠程序员“凭经验保证”,而是查虚函数表 + RTTI 信息,确认基类指针/引用背后**实际对象是否真是目标派生类型**。用错或绕开它(比如用 static_cast 强转),一旦类型不匹配,行为就是未定义的——可能崩溃、静默出错、数据错乱,且编译器完全不报错。
必须满足两个前提,否则 dynamic_cast 直接失效
dynamic_cast 不是万能钥匙,它只对「多态类型」起作用。漏掉任一条件,转换永远失败(返回 nullptr 或抛 std::bad_cast):
- 目标类体系中,基类**必须至少有一个虚函数**(通常加个虚析构函数
virtual ~Base() = default;最省事) - 执行转换时,源指针/引用所指的对象**必须是目标类型的完整对象**(不能是子对象片段,也不能是已析构对象)
常见错误:把普通 struct 或不含虚函数的 class 当作基类来 dynamic_cast,结果永远为 nullptr,但代码仍能编译通过。
指针 vs 引用:失败处理方式完全不同
用指针还是引用做 dynamic_cast,决定了你如何感知失败:
立即学习“C++免费学习笔记(深入)”;
- 转指针(如
Derived* d = dynamic_cast<derived>(b);</derived>):失败时返回nullptr,**必须显式判空**,否则解引用会崩溃 - 转引用(如
Derived& d = dynamic_cast<derived>(b);</derived>):失败时直接抛std::bad_cast异常,**必须用 try/catch 捕获**,否则程序终止
没有例外。别假设“反正我确定类型是对的”就跳过检查——RTTI 信息可能被编译器优化掉(如 GCC 的 -fno-rtti),或者对象内存已被重用,此时不检查等于埋雷。
static_cast 能向下转,但绝不“安全”
static_cast 确实允许写 static_cast<derived>(b)</derived>,但它只是按编译时声明的继承关系做偏移计算,**完全不查运行时类型**。这意味着:
- 如果
b实际指向的是Base对象(而非Derived),解引用d就是未定义行为 - 在多重继承中,若基类子对象不在首地址,
static_cast的偏移可能错,导致读到错误内存 - 它无法用于横向转型(cross-casting),而
dynamic_cast可以
所以,除非你 100% 控制对象生命周期、类型构造且禁用 RTTI(嵌入式极端场景),否则用 static_cast 做向下转型,就是在赌。
最易被忽略的一点:RTTI 不是默认“开启即可用”的魔法——它依赖编译器生成类型描述信息,而某些构建配置(如链接时 LTO、strip 符号、或明确关闭 RTTI)会让 dynamic_cast 失效却不报错。上线前务必在目标环境中实测转型逻辑。


















