[Cpp基础] [06] 强制类型转换

Last Updated on 2020年4月14日

强制类型转换

  • C++风格的类型转换为四个xxx_cast<TYPE>(var),每个都有特定的应用场合.
  • 转换总是通过创建临时量实现的,相当于TYPE tmp(var). 转换语句整体为tmp
  • 规定:仅有xxx_cast<TYPE &>(var)得到的临时量可以作为左值,其他情况都是右值。

const_cast

  • const_cast是只用于处理const相关的类型转换,例如加const或者去const
  • 由于转换会创建临时量,而const_cast一般会希望使用原始对象,所以很多场合都会向引用转换.
    const T c_obj;
    const T * p_c_obj=&c_obj;
    const T * const cp_c_obj=p_c_obj;
    T& wobj=const_cast<T&>(c_obj);//通过引用消const
    T * p_wobj=const_cast<T *>(p_c_obj);//消去指向对象的const
    const T * & p_c_obj2=const_cast<const T * &>(cp_cobj;)//消去指针自身的const    
    
    

static_cast

  • static_cast只用于处理编译期(静态)兼容类型间的类型转换.
    • 所有静态转换都要求tmp可以使用待转换值初始化.
    • static_cast无法获得运行时信息,只会进行普通的编译期检查.
  • 大部分内置数值类型之间都有预定义好的类型转换方法,彼此是兼容的.(截断/提升等)
  • void *指针和任意指针类型之间都有定义好的转换方法.
  • 原则上,const相关的转换只能由const_cast处理,但是有的编译器可能也会允许static_cast做这些工作

dynamic_cast

  • dynamic_cast只用于处理运行期(动态)类型转换.
    • 只有多态类型有动态类型转换.非多态类型的dynamic_cast一般会有编译期报错.
    • 类型转换在运行期执行,如果转换失败,会抛出异常或者返回null指针.
class A{virtual ~A(){}};
class B:public A{};
void f(A * pA){
    B * pB1=static_cast<B *>(pA);//静态转换,由用户保证pA一定指向一个B型实例
    B * pB2=dynamic_cast<B *>(pA);//动态转换,如果运行时pA指向的不是B型对象,就会报错.
}

reinterpret_cast

  • reinterpret_cast只用于内置数值类型,尤其是指针间的转换.用于保证转换前后的内存数值绝对相同.
    • 例如,对于含有多个虚函数表的多态类型,其指针之间进行转换时,static_cast/dynamic_cast会基于虚函数表偏移修改指针值,这种行为可以由reinterpret_cast抑制.

补充

  • 注意,多态类型是指有虚函数表的类型,这一类型的实例有vptr,而虚函数表中会存储类型自身的信息.如果没有vptr,那么对象中就不含类型信息,永远只能使用静态类型.
  • 对于非多态类型,typeid()总是获得其静态信息.对于多态类型typeid()可以在运行期获得对象类型.
  • 称 (TYPE)var 或者 TYPE(var)这样的C风格类型转换为旧式类型转换,其行为总是可以对应到4种C++转换风格中的一个或几个.因语义不清晰,不建议在C++中使用.