第二章 基本语言
第十节 类型转换: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: 重新解释,将操作数内容解释为另外一种不同的类型(能把操作的类型都转了),
处理无关类型的转换,也就是两个转换类型之间没有什么关系,就等于自由乱转,很随意常用于如下转换类型
将一个整型(地址)转换成指针, 一种类型指针转换成另一种类型指针,按照转换后的内容重新解释内存中的内容
也可以从一个指针类型转换成一个整型
- 范例一
#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只要好好用,合乎规则的用,不乱用,还是很好用的