1. 两者的对比
static_cast | dynamic_cast |
---|---|
速度更快 | 速度较慢 |
静态类型转换,在编译期间完成 | 动态类型转换,运行期间完成 |
派生类转父类 是安全的 | 派生类转父类 是安全的 |
父类转派生类 没有动态类型检查是不安全的 | 父类转派生类 如果转换失败会返回NULL |
如果两个类没有继承关系,编译会报错误 | 父类必须有虚函数,否则会报编译错误 |
注意: dynamic_cast 需要父类有虚函数的原因:运行时需要判断当前指针的类型,而这个信息存放在虚函数表中
2. 代码示例
class A
{
public:
virtual ~A() {}; // 需要有虚函数,否则无法用 dynamic_cast
int a = 1;
};
class B
{
public:
int b = 2;
};
class C : public A, public B
{
public:
int c = 3;
};
class D : public A
{
public:
int d = 4;
};
void Test1()
{
A* pA = new C;
B* pB = static_cast<B*>(pA); // 编译失败:A 和 B 之间没有继承关系
C* pC = static_cast<C*>(pA); // 成功
D* pD = static_cast<D*>(pA); // 编译成功,运行也没有报错,但是不符合预期,这两者之间不应该能够转换成功
}
void Test2()
{
A* pA = new C;
B* pB = dynamic_cast<B*>(pA); // 成功: 运行时会检测到pA 是 C 类型的指针,能够转换成 B 类型
C* pC = dynamic_cast<C*>(pA); // 成功
D* pD = dynamic_cast<D*>(pA); // 失败:相对于 static_cast 更符合预期
}
3. 小结
- static_cast 有更快的转换速度,但是安全性需要程序员自己保证
- dynamic_cast 具有更好的安全性,但是转换效率较低