C++基本语言:1.10类型转换:static_cast等

C++基本语言包含10章节内容,存于C++从入门到精通专栏

目录

一、隐式类型转换

​编辑二、显式类型转换(强制类型转换)

(1)static_cast:静态转换

可用于

不可用于

(2)dynamic_cast

(3)const_cast

(4)reinterpret_cast

三、总结

一、隐式类型转换

一个double和一个int做加 法运算,那么int会转换成double,然后再和double做运算,这个类型转 换是系统自动进行的,不需要人为介入,所以这种转换叫隐式类型转换。

 但如果用一个整型变量保存这个结果,因为是整型变量,不能保存小数部分,所以系统会把小数部分舍弃,把整数部分赋予这个变量,这也可以看作隐式类型转换。看如下代码:

aa323f8ed5324b22a4d5a899e6f0f363.png

二、显式类型转换(强制类型转换)

显式类型转换,也叫强制类型转换。

8d99de18d92247c4aee3fb0c1380a416.png

上面这个属于C语言风格的强制类型转换——直接把类型用“()” 括起来。

没有类型方面的检查,直接硬转,转的是对还是错,程序员必须提供保障。

除了把类型用“()”括起来之外,其实,如果不括类型,括数字也可以,括数字也称为函数风格的强制类型转换(看起来有点像函数调用):

51752e90a735419faeec2aa5d22962ec.png

在C++中,强制类型转换分为4种。

当然,C语言中的强制类型转换依然支持,但这种支持只是为了语言兼容性的考虑。

C++中的4种强制类型转换分别用于不同的目的

这4种强制类型转换,每一种都有一个不同的名字,提供更丰富的含义和功能以及更好的类型检查机制,方便代码的书写和维护。

强制类型转换(强制类型转换运算符或者强制类型转换操作符):

(a)static_cast

(b)dynamic_cast

(c) const_cast

(d)reinterpret_cast

这4种 强制类型转换都被称呼为“命名的强制类型转换”(因为它们每一个都 名字而且名字都不同)。

看一下这些命名的强制类型转换的通用形式:

4d49b5df665b4ee19430a23800dbbb12.png

强制类型转换名就是static_cast、dynamic_cast、const_cast、 reinterpret_cast 这四个名字之一,用来指定是哪种转换;type是转换的目标类型;express是要转换的值(你要转换的是谁)

(1)static_cast:静态转换

者就理解成正常转换,属于编译的时候就会进行类型转换的检查。代码中要保证转换的安全性和正确性,与C语言中的强制类型转换的感觉差不多

一般的编译器能够执行的隐式的类型转换 以及 C风格的强制转换都可以用static_cast来显式完成。

可用于

 ①相关类型转换,如整型和实型之间的转换。

6ba4f9767626430ba293efadf4f6953f.png

②后续学习类的时候,子类转成父类类型(有继承关系)也能用 static_cast。

这里简单看一下代码:

a010031eb3e04a49804281d6ebd17989.png

③void*与其他类型指针之间的转换:void *是属于“无类型指针”(万能指针) ,也就是可以指向任何的指针类型。

aeae11a3b2154da3a83a9c9844f1f4fd.png

不可用于

一般不能用于指针类型之间的转换,如int *转double *、float *转 double*等。

当然,如果本身是double*,然后要转成double*还是可以的

操作:其实具体可不可以转可以先把代码写出来,看看编译器包不报错

af4e8d2dd5e74e50b0e01a363b907057.png

(2)dynamic_cast

(2)dynamic_cast:该转换应用在运行时类型识别和检查

(与 static_cast不一样,static_cast是编译时类型检查)方面

主要用来进行父类型转成子类型,后面章节(3.10)会详细讨论。但是因为要做类型检查,所以检查的代价很昂贵,但也保证了转换的安全性。

(3)const_cast

const_cast:去除 指针或者引用的const属性。

换句话说,这 个转换能够将const性质转换掉,这个类型转换只能做这件事(功能比较有限)。同样,也属于编译的时候就会进行类型转换的检查。

f435efe21d8549af8a07682ff15cdbf4.png

一个一开始有const属性的东西你不要往里面写值,虽然语法上没错;但是这种写值行为,是一种未定义行为。

*pai2=120;//这种写值行为 是属于一种未定义行为,大家不要这么干

所谓未定义(不确定行为):与可能写进去也有可能没写进去,还有可能编译的时候写进去了,但是打印的时候没写进去

其实上面的代码也可以写成类似的C语言风格

53b50f602d2c43baa0a6b11c5f1854d5.png

请注意,如果本来是一个常量,若强硬地用const_cast去掉了常量性质并往里面写值,这是一种未定义行为,不要这样做,以免产生无法预料的后果。

除非它原来不是常量,后来被变为常量,再后来又用const_cast 给它变回非常量,这个时候能往里写值

const_cast很特殊,只有这个转换能去掉表达式的常量属性,所以这 个转换的能力是其他类型转换运算符无法替代的。 另外,const_cast也不能改变表达式类型。

c06ccefa37a24825b4985997a270b11b.png

(4)reinterpret_cast

reinterpret_cast:也属于编译的时候就会进行类型转换的检查。

reinterpret:重新解释、重新解读的意思(将所操作的内容解释为另一种不同的类型)

用来处理无关类型的转换,也就是两个转换的类型之间没有什么关系,那就等于乱转、瞎 转、自由转的意思,就是怎么转都行,所以这个类型转换相当随意。

常用于如下两种转换:

 ①将一个整型(地址)转换成指针、一种类型指针转成另外一种类型指针,按照转换后的类型重新解释内存中的内容。

②可从一个指针类型到一个整型进行转换

ac1e7699f465477fa0ea157d0ec33ac5.png

这种转换本身不报错,但这个地址本身存的是int(比如10),却把它转成字符指针("\n"),虽然转换成功(语法上对),但要是当成字符指针用,肯定程序会出错。

 当然,转成void*再转换回来还是可以的

277cb15f1cc04a1a8dc11b0e86a8304b.png

笔者不建议读者轻易使用这个类型转换,这个类型转换被认为是一种危险的类型转换,似乎功能非常强大,类型之间任意转,编译器都不会报错,但从写程序的角度来讲,如果随便乱转显然没有意义,只会导致程序运行出错。所以这个类型转换安全性很差(只在一些很特殊的场合下会用)。但是以后在读他人代码时,看到这个类型转换可以观察观察别人是怎样使用的。看看如下范例:

long64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1

f23683e236964adf8e8a0fb687a90513.png

//因为int*是4字节的,没办法保存8字节的东西

三、总结

(1)强制类型转换一般不建议使用。因为会干扰系统的正常类型检查。很多异常转换本来编译器会报错的,但是一旦用了这些类型转换,就会抑制编译器的报错行为

(2)如果读者有兴趣,可以对这些类型转换做任意自己能想到的尝试,也许能够发现一些很诡异的内容或者有一些新发现也说不定。本节的主要目的还是带着读者先认识一下这些类型转换符,以免以后遇到它们时不知所措。

(3)有句话叫使用reinterpret_cast非常危险,而使用const_cast 总是意味着设计缺陷。笔者觉得尤其要注意后面这半句话——读者如果真用到const_cast,就要检查检查自己代码的设计问题了,因为平白无故地 利用const_cast去掉const属性是很让人费解的设计。

(4)如果实在需要用到类型转换,建议全部用本节讲解的新风格。一般的, static_cast和reinterpret_cast就能很好地取代C语言风格的类型转换。

reinterpret_cast只要好好用,合乎规则,就很好用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梆梆显眼梆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值