C++基本语言包含10章节内容,存于C++从入门到精通专栏
目录
一、隐式类型转换
编辑二、显式类型转换(强制类型转换)
(1)static_cast:静态转换
可用于
不可用于
(2)dynamic_cast
(3)const_cast
(4)reinterpret_cast
三、总结
一、隐式类型转换
一个double和一个int做加 法运算,那么int会转换成double,然后再和double做运算,这个类型转 换是系统自动进行的,不需要人为介入,所以这种转换叫隐式类型转换。
但如果用一个整型变量保存这个结果,因为是整型变量,不能保存小数部分,所以系统会把小数部分舍弃,把整数部分赋予这个变量,这也可以看作隐式类型转换。看如下代码:
二、显式类型转换(强制类型转换)
显式类型转换,也叫强制类型转换。
上面这个属于C语言风格的强制类型转换——直接把类型用“()” 括起来。
没有类型方面的检查,直接硬转,转的是对还是错,程序员必须提供保障。
除了把类型用“()”括起来之外,其实,如果不括类型,括数字也可以,括数字也称为函数风格的强制类型转换(看起来有点像函数调用):
在C++中,强制类型转换分为4种。
当然,C语言中的强制类型转换依然支持,但这种支持只是为了语言兼容性的考虑。
C++中的4种强制类型转换分别用于不同的目的
这4种强制类型转换,每一种都有一个不同的名字,提供更丰富的含义和功能以及更好的类型检查机制,方便代码的书写和维护。
强制类型转换(强制类型转换运算符或者强制类型转换操作符):
(a)static_cast
(b)dynamic_cast
(c) const_cast
(d)reinterpret_cast
这4种 强制类型转换都被称呼为“命名的强制类型转换”(因为它们每一个都 名字而且名字都不同)。
看一下这些命名的强制类型转换的通用形式:
强制类型转换名就是static_cast、dynamic_cast、const_cast、 reinterpret_cast 这四个名字之一,用来指定是哪种转换;type是转换的目标类型;express是要转换的值(你要转换的是谁)
(1)static_cast:静态转换
者就理解成正常转换,属于编译的时候就会进行类型转换的检查。代码中要保证转换的安全性和正确性,与C语言中的强制类型转换的感觉差不多
一般的编译器能够执行的隐式的类型转换 以及 C风格的强制转换都可以用static_cast来显式完成。
可用于
①相关类型转换,如整型和实型之间的转换。
②后续学习类的时候,子类转成父类类型(有继承关系)也能用 static_cast。
这里简单看一下代码:
③void*与其他类型指针之间的转换:void *是属于“无类型指针”(万能指针) ,也就是可以指向任何的指针类型。
不可用于
一般不能用于指针类型之间的转换,如int *转double *、float *转 double*等。
当然,如果本身是double*,然后要转成double*还是可以的
操作:其实具体可不可以转可以先把代码写出来,看看编译器包不报错
(2)dynamic_cast
(2)dynamic_cast:该转换应用在运行时类型识别和检查
(与 static_cast不一样,static_cast是编译时类型检查)方面
主要用来进行父类型转成子类型,后面章节(3.10)会详细讨论。但是因为要做类型检查,所以检查的代价很昂贵,但也保证了转换的安全性。
(3)const_cast
const_cast:去除 指针或者引用的const属性。
换句话说,这 个转换能够将const性质转换掉,这个类型转换只能做这件事(功能比较有限)。同样,也属于编译的时候就会进行类型转换的检查。
一个一开始有const属性的东西你不要往里面写值,虽然语法上没错;但是这种写值行为,是一种未定义行为。
*pai2=120;//这种写值行为 是属于一种未定义行为,大家不要这么干
所谓未定义(不确定行为):与可能写进去也有可能没写进去,还有可能编译的时候写进去了,但是打印的时候没写进去
其实上面的代码也可以写成类似的C语言风格
请注意,如果本来是一个常量,若强硬地用const_cast去掉了常量性质并往里面写值,这是一种未定义行为,不要这样做,以免产生无法预料的后果。
除非它原来不是常量,后来被变为常量,再后来又用const_cast 给它变回非常量,这个时候能往里写值
const_cast很特殊,只有这个转换能去掉表达式的常量属性,所以这 个转换的能力是其他类型转换运算符无法替代的。 另外,const_cast也不能改变表达式类型。
(4)reinterpret_cast
reinterpret_cast:也属于编译的时候就会进行类型转换的检查。
reinterpret:重新解释、重新解读的意思(将所操作的内容解释为另一种不同的类型)
用来处理无关类型的转换,也就是两个转换的类型之间没有什么关系,那就等于乱转、瞎 转、自由转的意思,就是怎么转都行,所以这个类型转换相当随意。
常用于如下两种转换:
①将一个整型(地址)转换成指针、一种类型指针转成另外一种类型指针,按照转换后的类型重新解释内存中的内容。
②可从一个指针类型到一个整型进行转换
这种转换本身不报错,但这个地址本身存的是int(比如10),却把它转成字符指针("\n"),虽然转换成功(语法上对),但要是当成字符指针用,肯定程序会出错。
当然,转成void*再转换回来还是可以的
笔者不建议读者轻易使用这个类型转换,这个类型转换被认为是一种危险的类型转换,似乎功能非常强大,类型之间任意转,编译器都不会报错,但从写程序的角度来讲,如果随便乱转显然没有意义,只会导致程序运行出错。所以这个类型转换安全性很差(只在一些很特殊的场合下会用)。但是以后在读他人代码时,看到这个类型转换可以观察观察别人是怎样使用的。看看如下范例:
long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1
//因为int*是4字节的,没办法保存8字节的东西
三、总结
(1)强制类型转换一般不建议使用。因为会干扰系统的正常类型检查。很多异常转换本来编译器会报错的,但是一旦用了这些类型转换,就会抑制编译器的报错行为。
(2)如果读者有兴趣,可以对这些类型转换做任意自己能想到的尝试,也许能够发现一些很诡异的内容或者有一些新发现也说不定。本节的主要目的还是带着读者先认识一下这些类型转换符,以免以后遇到它们时不知所措。
(3)有句话叫使用reinterpret_cast非常危险,而使用const_cast 总是意味着设计缺陷。笔者觉得尤其要注意后面这半句话——读者如果真用到const_cast,就要检查检查自己代码的设计问题了,因为平白无故地 利用const_cast去掉const属性是很让人费解的设计。
(4)如果实在需要用到类型转换,建议全部用本节讲解的新风格。一般的, static_cast和reinterpret_cast就能很好地取代C语言风格的类型转换。
reinterpret_cast只要好好用,合乎规则,就很好用