C/C++中的类型转换

时间:2023-01-29 14:24:22

从c转向c++时,类型转换出现了一些疑惑,查阅了一些资料和博文,整理如下。


1. 隐式类型转换

这类转换主要发生在类型不同的赋值和计算过程中,C/C++中均存在

int ival = 3;
double dval = 3.124;
ival + dval //ival被提升为double类型
int *p = 0; // 0被转换为了int* 类型
ival = dval; // dval被转换为了int类型

还有很多类似的例子,比如传入函数的实参时,实参和形参类型不一致,实参转换为形参类型;函数返回值和return表达式类型不一致,转换为返回值等等


2. 显示类型转换

也被称为强制转换,顾名思义就是表达式中表明了如何转换。

  • C风格:(type-id)

    • C风格类型转换的底层实现一般禁止使用不安全的转换,也就是说其底层实现不是固定的使用哪种转换方式
  • C++风格:static_cast, dynamic_cast, reinterpret_cast, const_cast

    • 这里需要说明的是,为了清楚从字面上看出转换方式和潜在的风险,我们在编写代码的时候,尽量使用C++风格的强制转换,摒弃(type-id)的转换写法

下面对C++中几个转换类型做一些说明

  1. static_cast

    • 用法static_cast<type-id>(expression)

    • 将expression强制转换为type-id类型,该运算符的特点是转换时不进行检查,所以不具备安全性(特别是将父类指针向下转换为子类指针时,不对指针所指向的对象做动态类型检查

    • 不能转换掉expression的const、volatile、或者__unaligned属性。他也不是用来去掉static属性的

    • 可以用于指针、引用、基本类型、void类型等转换,对type-id和expression类型一致性没有要求

  2. dynamic_cast

    • 用法同上, type-id类的指针、引用或者void*类型;expression必须和type-id在类型上(此处指的是大范围的类型,指针、引用等,不具体到某个类)保持一致;

    • 具备类型检查的功能(所以有上述类型一致要求),在类指针的下行转换上,安全性要好

  3. const_cast

    • 此运算符是用来消除类型的const和volatile属性的。

    • 举例说明

      const char m = 't';
      const char *cm = &m;
      char *n = cm // error
      char *n = const_cast<char*>(cm) //OK
      *n = 'a'; // OK
      cout << *n << endl; // 'a'
      • char *n = (char *)cm 也是编译通过的,因为指针之间转换不做类型检查
    • 使用const_cast机会非常少,如果写代码需要用到const_cast,很大程度上说明代码设计有问题!

  4. reinterpret_cast

    • 用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整形数。

总结来说:

  • 最常用的还是static_cast和dynamic_static,其中前者更常用,后者多用于基类指针向下转换为子类指针。