天天看点

C++:18---强制类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast)一、static_cast二、const_cast三、reinterpret_cast四、dynamic_cast

旧式的强制类型转换

  • 在早期C/C++中,显式地进行强制类型的转换有以下两种形式:
C++:18---强制类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast)一、static_cast二、const_cast三、reinterpret_cast四、dynamic_cast

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

  • 命名的强制类型转换具有如下形式:
C++:18---强制类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast)一、static_cast二、const_cast三、reinterpret_cast四、dynamic_cast
  • cast-name可以是:static_cast、const_cast、dynamic_cast、reinterpret_cast
  • type是:转换的目标类型

避免强制类型转换

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

一、static_cast

  • 功能:用来强迫隐式类型转换,或称为显式的类型转换
  • static_cast还可以将一个左值转换为右值引用,介绍可以参阅:https://blog.csdn.net/qq_41453285/article/details/104447573
  • 例如:
    • 将非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常用于有函数重载的上下文,参阅:https://blog.csdn.net/qq_41453285/article/details/84843039

演示案例

  • 将底层const对象转换为非const对象
const char *pc;

//正确,但是通过p写值是未定义的行为
char *p = const_cast<char*>(pc); 
           
  • 当我们去掉某个对象的const性质之后,编译器就不再阻止我们对该对象进行写操作了,因此写操作会产生未定义的后果

演示案例

  • const_cast只能改变表达式的常量属性,而不能改变表达式的数据类型
const char* cp;

//错误,static_cast不能去除const性质
char*q = static_cast<char*>(cp);
	
//正确,字符串常量值可以转换为string类型
static_cast<string>(cp);

//错误,const只能去除const性质,但是不能进行数据类型的转换
const_cast<string>(cp);
           

三、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支持运行时类型识别,在另外一篇文章介绍:https://blog.csdn.net/qq_41453285/article/details/104704568

继续阅读