旧式的强制类型转换

  • 在早期C/C++中,显式地进行强制类型的转换有以下两种形式:

C++:18---强制类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast)_static_cast



C++的新式强制类型转换

  • 命名的强制类型转换具有如下形式:

C++:18---强制类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast)_const_cast_02

  • cast-name可以是:static_cast、const_cast、dynamic_cast、reinterpret_cast
  • type是:​转换的目标类型



避免强制类型转换

  • 强制类型转换干扰了正常的类型检查,所以强烈建议程序员避免使用强制类型转换
  • 这个建议对于reinterpret_cast尤其使用,因为此类类型转换总是充满了风险


一、static_cast

  • 功能:​用来强迫隐式类型转换,或称为显式的类型转换
  • static_cast还可以将一个左值转换为右值引用,​介绍可以参阅​
  • 例如:
  • 将非const对象转换为const对象(但是不能将底层const对象转换为非const对象,这个只有const_cast才能做到)
  • 将int转换为double,反之亦然
  • 也可以将void*指针转换为其他类型指针,将pointer-to-base转换为pointer-to-derived
  • 注意事项:
  • 使用static_cast会去除编译器的警告,但是我们必须自己清楚转换有效,否则转换无效可能会产生未定义的结果


演示案例

  • 我们​将一个整型对象转换为double类型

int i = 10, j = 1;

double slope1 = i / j; //一般的强制类型转换,编译器可能会报出警告
double slope2 = static_cast<double>(j) / j; //显式地强制类型转换,编译器无警告

  • 当我们把较大的算术类型赋值给较小的类型时,一般的强制类型转换编译器会发出警告
  • 但是当我们使用static_cast后,编译器就不会报出警告



演示案例

  • static_cast对于编译器无法自动执行的类型转换也非常有用
  • 例如我们可以使用static_cast找回存在于void*指针中的值:

double num = 3.14;

void *p = &num; //任何非常量对象的地址都能存入void*

double *dp = static_cast<double*>(p); //将void*转换回初始的指针类型


二、const_cast

  • 功能:​用来将对象的常量性移除
  • 注意事项:
  • 只能改变运算对象的底层const
  • const_cast只能改变表达式的常量属性,而不能改变表达式的数据类型
  • const_cast​常用于有函数重载的上下文,​参阅:
  • 三、reinterpret_cast
  • 功能:​通常为运算对象的位模式提供较低层次上的重新解释
  • 例如将一个pointer-to-int转换诶一个int
  • 使用reinterpret_cast是非常危险的,我们必须自己编写正确的代码
  • reinterpret_cast本质上依赖于机器。要向安全地使用reinterpret_cast必须对设计的类型和编译器实现转换的过程都非常了解


演示案例

  • 例如有下面的转换

int *ip;
char *pc = reinterpret_cast<char*>(ip);

  • 我们必须牢记​pc所指的真是对象是一个int而不是字符
  • 如果把pc当成普通的字符指针使用那么就会产生未定义的后果。例如:

int *ip;
char *pc = reinterpret_cast<char*>(ip);

//编译器虽然不报错,但是后果未定义
string str(pc);


四、dynamic_cast

  • dunamic_cast支持运行时类型识别,在另外一篇文章介绍​