c++ 不会直接将两个不同类型的值进行运算,而是先根据类型转换规则设法将运算对象的类型同一后再求值,上述的类型转换时自动执行的,被称作隐式转换。
算术转换
算术转换的一般性原则是是运算不损失精度,所以通常运算符的运算对象会被转换为最宽的类型。所以int与double类型相加时,int会被转换为double类型。
无符号类型的运算对象
如果一个无符号类型与一个带符号类型进行计算,而且其中的无符号类型不小于带符号类型,那么带符号类型会转换为无符号类型。此时如果带符号类型恰好是负数,则将产生出人意料的结果。
如果带符号类型大于无符号类型,此时转换的结果依赖于机器。如果无符号类型的所有值都能存在带符号类型中,那么无符号类型转换为带符号类型,否则,带符号类型将转换为无符号类型。
通常来说,我们应该避免让无符号类型与带符号类型一起参加运算。
其他隐式转换
数组转化为元素指针
0或者nullptr可以转换为任意指针类型;指向任意非常量的指针可以转换为void ,指向任意对象的指针可以转换为const void 。
指针可以转换为bool类型。
允许将指向非常量类型的指针转换为指向相应的常量的指针,对于引用也是如此,可以将任何非常量引用转换为常量引用,但是要注意,以上两种转换不可以逆向进行。
可以通过对类的一些处理,实现类类型定义的转换。但是编译器每次只能执行一种类类型的转换。
显示转换
显示转换又称为强制类型转换。
c++提供四种强制类型转换操作符static_cast,const_cast,dynamic_cast, reinterpret_cast.
static_cast
任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_const进行类型转换。
当需要把一个较大的算数类型转换为较小的类型时,static_cast非常有用。一般编译器发现一个较大的算数类型试图赋值给一个较小的类型时,就会给出一个警告信息。但是如果使用static_cast进行显示类型转换之后,警告信息就会被关闭。
const_cast
const_cast只能改变对象的底层const。
一旦我们去掉了某个对象的const属性,编译器就不会再阻止我们队该对象进行写操作。如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为。然而如果对象是一个常量,再使用const_cast执行写操作就会产生未定义行为。
const char *pc;
char *p = const_cast<char *>(pc); //正确,但是通过p写值是未定义的行为
const_cast常常用于有重载函数的上下文中。
reinterpret_cast
reinterpret_cast通常为运算对象的位模式提供低层次上的重新解释。
int *pi;
char *pc = reinterpret_cast<char *>(pi); //我们必须牢记pc所指向的真实对象是一个int而非一个字符
string str(pc); //导致异常,因为pc实际指向的是一个int对象,而不是一个字符数组
使用reinterpret_cast是非常危险的,其本质上依赖与机器,要想安全的使用它必须对涉及的类型和编译器实现转换的过程都非常了解。通常,最好不要使用reinterpret_cast。
旧式的强制类型转换
type(expr) //函数形式的强制类型转换
(type)expr //c风格
通常来说应该避免在程序中使用强制类型转换,尤其是reinterpret_cast。如果要使用强制类型转换,也应该使用c++提供的另外三种显示转换操作符来进行显示类型转换。