自动类型转换很重要,这有助于理解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)。
Tips:
c++的整型提升(自动转换)是保证数据不会丢失的。如short 比int短时,unsigned shor 转换为int,如果相同,unsigned shor会转换为unsigned int。同时wchar_t也会转会为容的下它的,int ,unsigned int,long,unsigned long。
2、不同类型之间的转换
(1)如果有一个操作数是long double,则将另一个操作数转换为 long double
(2)否则,如果有一个操作数是double,则将另一个操作数转换为 double
(3)否则,如果有一个操作数是float,则将另一个操作数转换为 float
(4)否则,说明操作数都是整型,因此执行整型提升
(4)这种情况下 如果凉饿操作数都是有符号或无符号,其中一个操作数的级别比另一个低,则转换为级别高的
(5)如果有一个操作数是有符号的,另一个操作数转换为 无符号,且无符号操作数的级别比有符号操作数高,则将有符号数转换为无符号操作数所属的类型
(6)否则,如果有符号数可以表示无符号数的所有取值则将无符号数转换为有符号操作数所属的类型
(7)否则,将两个操作数转换为有符号类型的无符号版本
上面的级别其实就是存储的容量的意思。总结一句化就是,如果另个操作数不一样,就帮小的哪个转换为大的哪个类型
这样做的好处是让计算机使用最自然的类型进行运行,这样有助于提升性能
传递参数时的类型转换
void f(int);
当我们调用这个个函数时,可以给它传递double 和short类型的参数因为这些类型c++会自动转换的。这样时ok的最多会有一个警告。
但是当我们由函数重载时
void f(int);
void f(short);
我们再给它传递double的参数时就会出错了,因为c++不知道截断成int的值还是short的值
类中的自动转换
A a= 19;
这样的语法是可以通过的。因为编译器将会调用A(int)构造函数,或者是类似A(int,double =1.0);来帮我初始化。想要关闭这种功能只需要在构造函数声明前面加上explicit关键字即可。如
explicit A(int);
explicit A(int,double =1.0);
这将关闭隐式的类型转换,而强制的类型转换是没有问题的。如下
A a;
a=19;//error
a=a(19);//ok,c++推荐的强制转换
a=(a)19;//ok,c的强制转换
使用构造函数的自动转换是危险的
那么我们为什么要用explicit限制这种行为呢?我们先来看看什么情况下会出现这种隐式转换呢。以上面的案例举例
- 将A类型对象初始化为int时
- int赋值给A类型的对象时
- 将int传递给接受A参数的函数时
- 返回值声明为A类型的函数试图返回int时
- 上述任意一种情况下,可以转化为int类型的基础类型
最后一条的意思说在没有使用explicit限定的情况下
class A a=19.0;
class A a=true
enum {SIZE=3}
class A a=SIZE;
都是没有问题的。
转换函数
A a=19
是没有问题的,那么 double i= a
可不可以呢?
这样做是可以的,但是需要使用转换函数,转换函数是用户自己定义的强制类型转换。格式如下:
operator typeName();
例如我在A中定义了
operator double(){return 19.0;}
我们就可以这样了
double d=double(a);//ok
double d=(double)a;//ok
double d=)a;//ok
但是c++对于转换函数是有限定的
- 转换函数必须是类的方法
- 转换函数不能指定返回类型
- 转换函数不能有参数
同样使用转换函数是危险的
- A类型赋值给double类型的对象时
- 将A类型传递给接受double类型参数的函数时
- 返回值声明为double类型的函数试图返回A类型时
- 上述任意一种情况下,可以转化为double类型的基础类型时
同样我们可以使用explicit关键字来限制这种行为
强制类型转换
(typeName) value;//来自c
typeName(value);//c++ 看起来更像函数
上述两种形式都是可以的,除此之外c++还有下面四种类型转换
①static_cast
②const_cast
③dynamic_cast
④reinterpret_cast
详情点击打开链接,或者自行百度。