定义:
dynamic_cast与static_cast是进行c++提供的类型转换的运算符,定义如下
dynamic_cast<type-id>(expression)
static_cast<type-id>(expression)
使用这两个运算符涉及到两个概念:
向上转换:
即派生类对基类的转换。
向下转换:
即基类指针向派生类的转换。
应用场景:
dynamic_cast仅支持类类型的类型转换,不能进行普通类型等的转换。
static_cast不仅支持类类型的类型转换,同样支持普通类型类型转换,该运算符的功能与C风格的强制转化,不同的是该运算符相对于C风格的强制类型转换更安全。
对于向上转换场景时,dynamic_cast和static_cast作用是一样的。
对于向下转换场景,dynamic_cast可以进行运行时检查比static_cast更安全
dynamic_cast 的type-id可以使指针,也可以是引用(包含左值引用和右值引用)
注意事项:
dynamic_cast运算符的使用必须保证基类中包含虚函数
static_cast的虽然会进行安全检查,但是其仅对类类型的无关类型进行检查,其余不进行检查,如下代码所示:
class A{...}
class B{...}
int main()
{
A* pA = new A;
B* pB = static_cast<B*>(pA); //编译报错,因为类A和类B没有任何关系
}
static_cast是编译阶段进行的检查
dynamic_cast是运行阶段进行类型检查的,依赖于类中虚函数表中的typeinfo字段进行检查。通过查阅typeinfo中的类型信息以及继承关系,实现类型的转换检查。
感悟:
对于这两个运算符我们可能存在这样的印象,就是大概知道有这么个东西,功能也大概清楚,但是仔细一想,好像又不知道具体是如何使用的。产生这种现象的根本原因是对于这两个运算符的理解流于表面,时间长了自然也就模模糊糊了。通过查阅一些资料,现将理解总结如下(这里重点介绍类类型的转换):
对于类类型转换而言,一般是用于基类和派生类之间的转换。
从内存角度看进行类类型的转换就是内存的截取或者扩展。当基类指针转换为派生类指针可以理解为内存的扩张;当派生类指针转换为基类指针时可以理解为内存的截断。
对于dynamic_cast进行转化时为什么要求基类必须至少含有一个虚函数呢?究其根源在于dynamic_cast进行类型安全检查的机制是通过虚函数表获取typeinfo,typeinfo中记录类型信息以及继承信息,通过这些来实现类型的安全检查。
基类指针转换为派生类指针是不安全的理解?即向下转换是不安全的理解。因为基类的子类可以有多个,一个指向子类1的对象的基类指针如果转换为子类2 的指针,就会发生错误。向下转换就是一个指向子类对象的基类指针转换为对对应的子类对象。铺开来说,如果子类对象1的指针付给基类指针,然后将该指针强转为对象2,从内存的角度看这是不合理的。所以说向下转换是不安全的,这个时候就需要通过调用dynamic_cast来解决这个问题。不安全的根本原因是基类可以有多个子类,强制转换可能会造成不同子类间的转化,这是非常危险的。运行时可能会因为访问非法内存而造成程序成奎。
参考链接: