如果两种类型可以相互转换(conversion),那么他们是关联的
如
int ival = 3.541+3;//编译器可能会警告运算损失了精度
会将类型转换后再执行,称为 隐式转换(implicit conversion)
算数类型的隐式转换会尽可能避免失去精度,如上述的例子 3会被转换成double,得到的结果是double并把double赋给int
何时发生隐式类型转换
- 大多数表达式中,比int类型小的整型值首先提升为较大的整数类型
- 在条件中,非布尔值转换成布尔类型
- 在初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型
- 如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型
- 函数调用时也会发生类型转换
4.11.1 算术转换
算术转换(arithmetic conversion)是把一种算术类型转换成另外一种算术类型
整型提升
整型提升(integral promotion)负责把小整数类型转换成较大的整数类型。
对于 bool,char,signed char, unsigned char, short 和 unsigned short等类型来说,只要它们所有可能的值都能存在 int 里,他们就会提升成 int 类型; 否则,提升成unsigned int 类型。
如 false提升成 0,true提升成1
较大的char类型(wchar_t,char16_t,char32_t)被提升成int ,uunsigned int , long ,unsigned long ,
long long和 unsigned long long 中最小的一个
无符号类型的运算对象
如果一个运算对象是无符号类型,另一个运算对象是带符号类型,而且其中的无符号类型不小于带符号类型,带符号类型会转换成无符号的(为什么不把无符号转成带符号?因为无符号要>=带符号类型)
如果是带符号类型大于无符号类型,此时依赖于机器,如果无符号所有值都能存在带符号类型中,则无符号类型的运算对象转换成带符号类型,如果不能则反之
理解算术转换
(一些算术转换)
P143 略
4.11.2 其他隐式类型转换
数组转换成指针
:在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针
当数组被用作 decltype 关键字的参数,或者作为 取地址符(&),sizeof即typeid等运算符的运算对象时,
上述转换不会发生。如果用一个引用来初始化数组,上述转化也不会发生
指针的转化
:C++规定了其他的指针转换方式
包括常量整数值0或者字面值nullptr能转换成任意指针类型;
指向任意非常量的指针能转换成 void*
指向任意对象的指针转换成 const void*
有继承类关系中还有一种
转换成布尔类型:
存在一种从算术类型或指针类型向布尔类型
转换成常量:
允许将指向非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样
如果说T是一种类型,我们就能将指向T的指针或引用转换成指向 const T
int I;
const int &j = I; //非常量转换成const int的引用
const int *p = &I;//非常量的地址转换成const大的地址
类类型定义的转换:
string s , t ="A string"; //字符串字面值转换成string类型
while(cin>>s) ; //while 的条件部分把cin转换成布尔值
4.11.3 显示转换
强制类型转换(cast)
warning:虽然有时不得不使用强制类型转换,但这种方法本质上是非常危险的。
命名的强制类型转换
形式如下
cast-name<type>(expression);
type是转换的目标类型而expression是要转换的值
如果type是引用类型,则结果是左值
cast-name是 static_cast , dynamic_cast, const_cast , reinterpret_cast 其中的一种
static_cast
具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast
double slope = static_cast<double>(j) / I;
static_cast对强制转换为原来的类型时(找回void*)
void* p = &d;
double *dp = static_cast<double*>(p);
应保证指针的值保持不变,
强制类型的结果将于原始的地址值相等,因此我们必须确保转换后所得的类型就是指针所指的类型。
类型一旦不符将产生未定义的后果
const_cast
const_cast 只能改变运算对象的底层const
const char *pc;
char *p = const_cast<char*>(pc);//正确:但是通过p写值未定义
const_cast 只能去掉const性质(cast away the const),不能改写对象类型;
const_cast常常用于有函数重载的上下文中
reinterpret_cast
reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释
warning:reinterpret_cast 本质上依赖于机器。想要更安全的使用reinterpret_cast必须对设计的类型和编译器实现转换的过程都非常了解
建议:避免强制类型转换
旧式类型的强制类型转换
在早期c++语言中,显示强制转换包含两种形式
type(expr); //韩叔叔形式的强制类型转换
(type) expr; //c语言形式的强制类型转换
在某处执行旧式的强制类型转换,如果换成const_cast,static_cast也合法,则其行为与对应命名转换一致
如果替换后不合法,则与 reinterpret_cast类似的功能的效果一样
warning: 与命名的强制类型转换相比,旧式的强制类型转换从表现形式上来说不那么清晰,很难被追踪