C++ 类型转换

C++的类型转换比较杂,看了又忘,再看也忘。在此,总结了一下。

隐式转换

何时发生隐式转换

  • 在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型(整型提升)。
  • 在条件中,非布尔值转换成布尔类型。
  • 初始化过程中,初始化值转换成变量类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型。
  • 如果算术运算或关系运算的运算有多种类型,需要转换成一种类型(算术转换)。
  • 函数调用时也会发生类型转换。

转换规则

算术转换

运算符的对象转换成最宽的对象。当表达式中既有浮点型也有整型类型时,整型值也转换成浮点型。

整型提升

小整数类型转换成较大的整数类型,对于boolcharsigned charunsigned charshortunsigned short,只要它们所有可能的值都能存在int里,它们就会提升成int类型,否则提升成unsigned int类型。

较大的char类型(wchar_tchar16_tchar32_t)提升成intunsigned intlongunsigned longlong longunsigned long long中最小的一种类型。

无符号类型的运算对象

首先进行整型提升,提升后如果符号相同则小类型转换大类型。如果符号不同,而其中无符号类型不小于带符号类型,则都转成无符号的;如果带符号类型大于无符号类型,如果无符号类型的所有值都能存在带符号类型中,则无符号转成带符号,如果不能,那么带符号转换无符号。

派生类到基类转换

  • 派生类型向基类类型转换只对指针或引用有效。
  • 基类向派生类不存在隐式类型转换。
  • 转换可能访问受限:
    • 只有公有继承时,用户代码才能使用该转换。
    • 任意方式继承,成员函数和友元都能使用该转换。
    • D 公有继承或保存继承 B 时,则 D 的派生类的成员或友元才能使用 B 向 D 的转换。
  • 能够将一个派生类对象拷贝、移动或赋值给一个基类对象,不过只处理派生类对象的基类部分。

隐式的类类型转换(转换构造函数)

能通过一个实参调用的构造函数定义了一条从构造函数的类型向类类型的隐式转换规则,只允许一步类类型转换(内置类型转换除外)。

可以使用explicit抑制构造函数定义的隐式转换。

其它隐式类型转换

  • 数组自动转换成指针。
  • 指针的转换:nullptr能转换成任意指针类型;指向任意非常量的指针能转换成void*;指向任意对象的指针能转换成const void *;继承关系指针的转换。
  • 转换成布尔类型:如果指针或算术类型的值为0,转换结果为false;否则转换结果是true
  • 转换成常量:指向 T 的指针或引用分别转换成指向const T的指针或引用(顶层const)。
  • 类类型定义的转换。

显式转换

  • static_cast:只要不包含底层const,都可以使用static_cast
  • const_cast:只能改变运算对象的底层const,如果对象本身是一个常量,那么行为未定义。
  • reinterpret_cast:为运算对象的位模式提供较底层次上的重新解释。
  • 旧式强制类型转换:
    1
    2
      type (expr);
      (type) expr;