类型转换很重要,这有助于理解c++的工作细节,可以分为自动类型转换和强制类型转换
自动类型转换
①将一种算术类型的值赋值给另一种算术类型的变量时,c++对值进行转换
②表达式中包含不同的类型时,c++对值进行转换
③将参数传递给函数时,c++将对值进行转换
④当类定义了特殊的函数的时候,类的对象可能会转换成基本类型,基本类型可能会转换为对象。
初始化和赋值中的转换
c++中的基本类型之间有时会会进行自动转换,我们称之为标准转换,但是由”小“转“大”是没有问题的,但是反过来就有可能出现下面问题:
- ①将较大的浮点类型转换为较小的浮点类型,如double到float,精度降低,值坑能超出目标类型的取值范围,在这种情况下,结果将不正确
- ②浮点转换为整形,小数部分将会被截断
- ③较大整形转换为较小整形,原来的值可能超出目标类型的取值范围
- ⑤bool 和整型(0,1)会在c++编译器需要的时候相互转换
示例
#include<iostream>
using std::cout;
using std::endl;
using std::ios_base;
bool print(void );
int main(){
cout.setf(ios_base::fixed,ios_base::floatfield);//定义输出方式
float tree=3;//转换成浮点数3.0
int guess(3.98E32);//会被截断,且不确定其值
int debt=7.2812;//7
cout<<"tree="<<tree<<endl;
cout<<"guess="<<guess<<endl;
cout<<"debt="<<debt<<endl;
return 0;
}
输出结果:
tree=3.000000
guess=2147483647
debt=7
表达式中的转换
分为两种
1、整型提升
bool,char,unsigned char ,signed char,short,将会被转换为int。这种转换叫做整型提升(integer promotion)。因为在计算机中整型是最讨cpu喜欢的,所以在表达式中小于整型的类型会被转换成整型来进行运算,这样会比较块
Tips:
c++编译器进行整型提升是的前提是保证数据不会丢失的。例如short 比int短时,unsigned shor 转换为int,如果相同,unsigned shor会转换为unsigned int。
2、不同类型之间的转换
(1)如果有一个操作数是long double,则将另一个操作数转换为 long double
(2)否则,如果有一个操作数是double,则将另一个操作数转换为 double
(3)否则,如果有一个操作数是float,则将另一个操作数转换为 float
(4)否则,说明操作数都是整型,因此执行整型提升
(4)这种情况下 如果两个操作数都是有符号或无符号,其中一个操作数的级别比另一个低,则转换为级别高的
(5)如果有一个操作数是有符号的,另一个操作数转换为 无符号,且无符号操作数的级别比有符号操作数高,则将有符号数转换为无符号操作数所属的类型
(6)否则,如果有符号数可以表示无符号数的所有取值则将无符号数转换为有符号操作数所属的类型
(7)否则,将两个操作数转换为有符号类型的无符号版本
上面的的级别就是数据类型的容量。总结一句化就是,如果两个操作数不一样,就帮小的哪个转换为大的哪个类型
传递参数时的类型转换
函数参数的自动转换我们分为两种情况讨论
1、对于基本类型的参数函数,如
void f(int ,int);
上面的的函数接受什么类型的参数呢。还记的上面说的标准转换和整型提升吗。只要满足它们两都是可以被接受的。但是要注意标准转换带来的不安全性。如下
f(double,int);//不安全
f(short,short);//ok,安全
f(bool.bool);//ok,安全
f(long,long)//不安全
2、而对于指针和引用等,就完全不一样了
void f1(int & ,int &);
//或者
void f2(int *,int*)
上面的函数接受的实参类型就要非常严格了。比如你不能把一个指向或者引用一个double/short的值传递进去。但是你却可以把int的类型的变量赋值给f1,把一个一维int数组复制给f2。这就要说到完全匹配的概念了
从实参 | 到形参 |
---|---|
Type | Type& |
Type& | Type |
Type[] | Type* |
Type(argument-list) | Type(*)(argument-list) |
Type | const Type |
Type | volatile Type |
Type* | const Type* |
Type* | volatile Type* |
上面的表列出了所有的完全匹配,曲中Type 表示任意类型,而Type(argument-list)表示函数特征,而完全匹配就是”等价“的意思,例如,比那在参数泪飙中编译器不区分 int &和 int,int[]|int*。
强制类型转换
下面两种方式都是正确的。
(typeName) value;//来自c
typeName(value);//看起来更像函数
①static_cast
②const_cast
③dynamic_cast
④reinterpret_cast
详情点击这里,或者自行百度。