C++ 类型转换
C 风格强制转换
当等号两边的类型不同的时候、形参与实参类型不匹配的时候、返回值类型与接收返回值类型不一致时,就需要发生类型转化。
而类型转换又分为隐式类型转换和显式类型转换。
隐式类型转换
// 隐式类型转换
int Ival = 1;
double Dval = Ival;
隐式类型转换是编译器在编译阶段自动进行,能转就转,不能转就编译失败。
显式类型转换
格式: TYPE a = (TYPE) b
即通过圆括号直接转型,常见有以下几种情况:
- 浮点数赋值给整型,舍弃小数部分(符合一般思维,可放心使用)。
- 整数赋值给浮点型,数值不变,底层改用指数格式存储(符合一般思维,可放心使用)。
- double型小数赋值给float型小数,精度略微损失,可能出现数值范围溢出(小心使用)。
- 字符赋值给整数型,保留原字节数据,因为字符本身就是用ASCII码表示的,本质就是八位的较小整数(理解字符的存储方式,就很容易接受)。
- 整数赋值给字符型,截断高地址数据,只保留低地址的八位,因为char型最多只有八位(小心使用)。
- 有符号整数赋值给无符号整数,将包括符号在内的全部字节的直接赋值,实际数值会改变(小心使用)。
- 无符号整数赋值给有符号整数,也是将包括符号在内的全部字节的直接赋值,但是数值可能会改变(小心使用)。
unsigned int和int字节存储区别:unsigned int和int位数是一样的,但是int将首个bit位作为正负号,0表示正数,1表示负数。unsigned int和int之间都是以字节的方式相互赋值。当字节以0开头时,它们表示的数值是相同的,当字节以1开头时,它们则分别表示整数和负数。由于int将首位作为符号位,因此它实际能表示的最大正整数只有unsigned int的一半。
C++ 四种类型转换方式
static_cast
static_cast 是一个C++运算符,功能是把一个表达式转换为某种类型,类似C风格的强制转换,但没有运行时类型检查来保证传唤的安全性。
格式:TYPE a = static_cast <TYPE>(expression)
用法:
- 用于类层次结构中基类(父类)和派生类(子类)之间的指针或引用的和转换。
进行向上转换(将派生类的指针或引用转换成基类表示)是安全的;进行向下转换(将基类指针或者引用转换为派生类表示)时,由于没有动态类型的检查,所以是不安全的。 - 用于基本数据类型之间的转换。
如把int转换为char,把int转换为enum。这种转换的安全性也要开发人员来保证。 - 把空指针转换成目标类型的空指针。
- 把任何类型的表达式转换为void类型。
注意事项: static_cast 不能转换掉expression的const、volatile或者__unaligned属性。
dynamic_cast
dynamic_cast是将一个基类对象指针(或引用)转换到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理。虽然static_cast也具备这样的功能,但是是不安全的,dynamic_cast则会在转型时判断类型,如果类型不符则返回nullptr。
由于类型信息是保存在虚函数表中的,因此dynamic_cast操作的基类必须包含virtual函数。
dynamic_cast运算符涉及到编译器的属性设置,而且牵扯到的面向对象的多态性跟程序运行时的状态也有关系,所以不能完全的使用传统的替换方式来代替。但是也因此它最常用,是最不可缺少的一个运算符。
格式: TYPE a = dynamic_cast<TYPE>(expression)
说明:
该运算符把expression转换成TYPE类型的对象。TYPE必须是类的指针、类的引用或者void*;如果TYPE是类指针类型,那么expression也必须是一个指针,如果TYPE是一个引用,那么 expression 也必须是一个引用。
dynamic_cast运算符可以再执行期决定真正的类型。如果downcast是安全的(也就是说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果downcast不安全,这个运算符会传回空指针(即基类指针或者引用没有指向一个派生类对象)。
用法:
- dynamic_cast在类层次间进行向上转换时,效果和static_cast一样。
- dynamic_cast在类层次间进行向下转换时,具有类型检查功能,更安全。
reinterpret_cast
首先从英文字面的意思理解,interpret是“解释,诠释”的意思,加上前缀“re”,就是“重新诠释”的意思;cast在这里可以翻译成“转型”,这样整个词顺下来就是“重新诠释的转型”。
顾名思义,reinterpret_cast就是不改变指针地址,但是强制将地址处的内存字节解释为某种类型的数据。
reinterpret_cast转换的实质是让编译器重新给出对象的比例模型而不进行二值转换。也就是让编译器按照目标转换类型在内存中所占的比特位重新编译原始数据类型。转换前后对象的地址值是不变的,只是对象的读取内存的比例变了而已。
格式: TYPE a = reinterpret_cast<TYPE>(expression)
TYPE必须是一个指针,引用,算术类型,函数指针,成员指针等。reinterpret_cast可以把一个整型转换为指针,也可以把一个指针转换为整型。总结来说,reinterpret_cast可以允许任何指针类型(引用)之间的转换,整型与指针类型间的转换以及指针与足够大的整型之间的转换。
reinterpret_cast 实测:C+±----reinterpret_cast
const_cast
const_cast是一个基于C语言编程开发的运算方法,用于常量指针和非常量指针间的转换,同样适用于引用、函数和模块接口,其主要作用是:修改类型的const或volatile属性。
volatile详解:volatile-百度百科
即便是在单个文件中,我们也可能希望某个变量在大多时候值不被修改,但是在某个特定地方却又必须修改它的值,这时const_cast就派上用场了。
const_cast提供了一个解决特殊需求的捷径,但是不应当滥用,否则const属性就失去意义了
格式: TYPE a = const_cast <type-id>(expression)
说明:上述格式中,除了const或volatile修饰之外,TYPE和expression的类型是一样的。