ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

【c++】c语言入门到c++使用高手:深入学习C++之基本语言(十)

【c++】c语言入门到c++使用高手:深入学习C++之基本语言(十)

第二章 基本语言

第十节 类型转换:static_cast、reinterpret_cast等

1.隐式类型转换

  • 系统自动进行,不需要程序开发人员介入
#include<iostream>using namespace std;intmain(){// 把小数部分截掉,隐式类型转换inta=3+46.6;floatb=3+46.6;cout<<a<<" "<<b<<endl;return0;}

2. 显式类型转换(强制类型转换)

#include<iostream>using namespace std;intmain(){// int k = 5 % 3.2;语法错误// c语言风格的强制类型转换intk=5%(int)3.2;// 函数风格的强制类型转换(c语言风格的强制类型转换)intk1=5%int(3.2);return0;}
  • c++强制类型转换分为四种,这4种强制类型转换,分别用于不同的目的,提供4种的目的,提供更丰富的含义和功能,更好的类型检查

  • static_cast, dynamic_cast, const_cast, reinterpre_cast,这4种强制类型转换都被称呼为"命名的强制类型转换",
    因为它们每个都有一个名字并且名字各不相同

  • 通用形式: 强制类型转换名(express), 强制类型转换名,是上边的四种名字, type:转换的目标类型,express:需要转换的值

2.1 static_cast

-静态转换, 正常转换,编译的时候就会进行类型转换的检查,代码中要保证转换的安全性和正确性,
static_cast含义跟c语言中强制类型转换这种差不多, c风格的强制类型转换以及编译器能够进行的隐式
类型转换,都可以用static_cast来显示完成

可用场景
  • 相关类型转换:整型和实型之间
doublef=100.34finti=(int)f;inti2=static_cast<int>(f);//c++风格的类型转换
  • 后续学习类的时候子类转成父类类型(继承关系),也能用这个static_cast转
#include<iostream>using namespace std;// 父类class A{};// 子类, 公有继承父类class B:public A{};intmain(){B b;// 把子类转成父类的对象A a=static_cast<A>(b);return0;}
  • void*与其他类型指针之间的转换,void*:无类型指针,可以指向任何指针(万能指针)
#include<iostream>using namespace std;intmain(){inti=10;int*p=&i;// int* 转成 void*void*q=static_cast<void*>(p);int*db=static_cast<int*>(q);return0;}
不可使用场景
  • 一般不能用于指针类型的转换,比如int *转double *, float *转double *等等
#include<iostream>using namespace std;intmain(){doublef=100.0f;double*pf=&f;//会报错,方案不可行// int *i = static_cast<int*>(pf);return0;}
2.2 dynamic_cast
  • 主要应用于运行时类型识别和检测,主要用来父类型和子类型转换用的,
    (父类型指针指向子类型对象,用dynamic_cast把父类型指针把子指针类型转,第三章会详细讲解)
2.3 const_cast
  • 去除指针或者引用的const属性,该转换能够将const性质转换掉,编译时就会进行类型转换
#include<iostream>using namespace std;intmain(){constintai=90;// 不可行, ai不是指针也不是引用//int ai2 = const_cast<int>(ai);constint*pai=&ai;int*pai2=const_cast<int*>(pai);// 语法正确,这种写值行为是一种未定义行为, 还是尽量不要着这么做*pai2=100;cout<<ai<<endl;//90cout<<*pai<<endl;//100cout<<*pai2<<endl;//100return0;}
2.4 reinterpre_cast
  • 编译的时候就会进行类型转换的检查

  • reinterpre_cast: 重新解释,将操作数内容解释为另外一种不同的类型(能把操作的类型都转了),
    处理无关类型的转换,也就是两个转换类型之间没有什么关系,就等于自由乱转,很随意

  • 常用于如下转换类型

  1. 将一个整型(地址)转换成指针, 一种类型指针转换成另一种类型指针,按照转换后的内容重新解释内存中的内容

  2. 也可以从一个指针类型转换成一个整型

  • 范例一
#include<iostream>using namespace std;intmain(){inti=88;int*pi=&i;int*p2=reinterpret_cast<int*>(pi);char*p3=reinterpret_cast<char*>(pi);cout<<*p2<<endl;// 88cout<<*p3<<endl;// Xreturn0;}
  • 范例二
#include<iostream>using namespace std;intmain(){inti=88;int*pi=&i;void*p2=reinterpret_cast<void*>(pi);// 一些操作int*p3=reinterpret_cast<int*>(p2);cout<<*p3<<endl;// 88return0;}
  • 功能上非常强大,但是使用起来非常危险,安全性比较差

任意转,这段代码意义不大…

#include<iostream>using namespace std;intmain(){inti=88;longlonglv1=88888888888;// 16进制输出cout<<hex<<lv1<<endl;// c风格int*piv1=(int*)i;cout<<piv1<<endl;int*piv2=reinterpret_cast<int*>(lv1);cout<<piv2<<endl;return0;}

3. 总结

  • 强制类型转换不是必须,不建议使用,强制类型转换能够抑制编译器报错,尽量少用

  • 学习的目的:认识这些类型转换符,方便大家阅读别人代码

  • 资料说: reinterpret_cast非常危险,使用const_cast意味着设计缺陷

  • 如果要使用类型转换,不要再使用c语言风格的类型转换,使用c++中的类型转换即可

  • 一般使用static_cast和reinterpret_cast就能够很好的取代c语言风格的类型转换

  • reinterpret_cast只要好好用,合乎规则的用,不乱用,还是很好用的

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进