文章目录
- 前言
- 一、 类型检查的时机
- 二、安全性
- 三、适用场景
- 四、代码示例对比
- 总结
前言
在 C++ 中,dynamic_cast 和 static_cast 是两种不同的类型转换操作符,主要区别体现在类型检查的时机、安全性和适用场景上。以下是它们的核心区别:
一、 类型检查的时机
-
dynamic_cast:
运行时检查。它会验证转换的合法性(比如指针或引用是否指向目标类型的有效对象)。如果转换非法,对指针返回 nullptr,对引用抛出 std::bad_cast 异常。
要求类必须有虚函数(即多态类型),否则无法使用。 -
static_cast:
编译时检查。它信任开发者对类型安全的保证,不执行运行时检查。如果转换非法(比如无关类之间的转换),可能导致未定义行为(UB)。
适用于编译时已知类型关系的场景。
二、安全性
-
dynamic_cast:
更安全,但需要运行时开销(RTTI)。
主要用于多态类型的向下转型(downcast)或交叉转型(crosscast)。 -
static_cast:
不安全,但性能更高(无运行时开销)。
需要开发者自行确保类型兼容性,否则可能导致错误。
三、适用场景
dynamic_cast 的典型用途
- 多态类型(有虚函数的类)的向下转型:
class Base { virtual void foo() {} };
class Derived : public Base {};Base* ptr = new Derived;
Derived* derived_ptr = dynamic_cast<Derived*>(ptr); // 安全向下转型
- 处理继承层次中的交叉转换(如多重继承中的兄弟类转换)。
static_cast 的典型用途
- 基本类型的显式转换(如 double → int):
double d = 3.14;
int i = static_cast<int>(d);
- 非多态类型的指针/引用转换(需确保类型兼容):
Derived* d = new Derived;
Base* b = static_cast<Base*>(d); // 向上转型(安全,无需 dynamic_cast)
- 显式反向转换(如 void* → int*):
void* vptr = some_address;
int* iptr = static_cast<int*>(vptr);
四、代码示例对比
向下转型(多态类型)
class Base { virtual void foo() {} }; // 必须有多态性(虚函数)
class Derived : public Base {};Base* base_ptr = new Derived;// 使用 dynamic_cast(安全,但需要虚函数)
Derived* derived_ptr1 = dynamic_cast<Derived*>(base_ptr); // 成功// 使用 static_cast(不安全,但强制转换)
Derived* derived_ptr2 = static_cast<Derived*>(base_ptr); // 可能未定义行为(若实际类型不匹配)
class Base { virtual void foo() {} };
class Derived : public Base {};Base* ptr = new Derived;
Derived* derived_ptr = dynamic_cast<Derived*>(ptr); // 安全向下转型
非多态类型转换
class A {};
class B : public A {};A* a_ptr = new B;
B* b_ptr = static_cast<B*>(a_ptr); // 编译通过,但无运行时检查
// B* b_ptr = dynamic_cast<B*>(a_ptr); // 错误:A 不是多态类型(无虚函数)
总结
特性 | dynamic_cast | static_cast |
---|---|---|
类型检查时机 | 运行时 | 编译时 |
安全性 | 高(失败返回 nullptr 或抛异常) | 低(依赖开发者保证) |
性能 | 有运行时开销(RTTI) | 无开销 |
适用类型 | 多态类型(需虚函数) | 任意类型(包括非多态) |
典型用途 | 向下转型、交叉转型 | 基本类型转换、显式向上/向下转型 |
优先选择 static_cast,除非需要处理多态类型的不确定转换(此时用 dynamic_cast)。