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只要好好用,合乎规则,就很好用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/318356.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化测试框架 —— pytest框架入门到入职篇

01、pytest框架介绍 pytest 是 python 的第三方单元测试框架,比自带 unittest 更简洁和高效,支持非常丰富的插件,同时兼容 unittest 框架。这就使得我们在 unittest 框架迁移到 pytest 框架的时候不需要重写代码。 pytest框架优点 1、简单…

数字IC设计——数字电路基本元器件

现代数字集成电路基本由CMOS晶体管构成,而CMOS门电路由PMOS场效应管和NMOS场效应管以对称互补的形式组成,所谓“互补”,即利用互补型MOSFET,即pMOS和nMOS,二者成对出现构成互补电路。 这种电路具有高的电路可靠性和抗干…

循环与基础函数

循环与函数 1.循环的三种方式2.循环的中断与空语句3.函数的定义与使用4.参数的作用域5.指针6.总结 1.循环的三种方式 我们最熟悉的循环为for和while,这两种循环方式在Python系列介绍过。在C中,循环的基本逻辑同Python是类似的。c中while循环的语法如下&…

使用Matplotlib绘制模拟上海城市气温变化图

模拟上海气温变化折线图 实现步骤 准备数据创建画布绘制图像显示图像 基本实现 示例代码: import matplotlib.pyplot as plt import random# 准备数据 x range(60) y_shanghai [random.uniform(15,18) for _ in x]# 创建画布 plt.figure(figure(20,8), dpi10…

【致远OA】获取指定人员的协同待发列表

接口请求说明 V6.0接口更新:不在传入ticket,改为传memberId人员ID V6.0之前http请求方式:GET http://ip:port/seeyon/rest/affairs/draft 如 http://127.0.0.1/seeyon/rest/affairs/draft?ticketxxxxxx V6.0http请求方式:GET http://ip:p…

华为路由器和交换机恢复出厂配置实操

//用户视图下输入重置交换机配置命令 <sw1>reset saved-configuration //提示将删除交换机当前配置文件&#xff0c;是否继续&#xff0c;输入Y Warning: The action will delete the saved configuration in the device. The configuration will be erased to reco…

算法巡练day04Leetcode24交换节点19删除倒数节点142环形链表

今天学习的文章和视频链接 https://www.bilibili.com/video/BV1YT411g7br/?vd_source8272bd48fee17396a4a1746c256ab0ae https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source8272bd48fee17396a4a1746c256ab0ae 24两两交换链表中的节点 给你一个链表&#xff0c;两两…

Springboot集成RabbitMq一

0、知识点 1、创建项目-生产者 默认官方start.spring.io已不支持自动生成低版本jkd的Spring项目&#xff0c;自定义用阿里云的starter即可&#xff1a;https://start.aliyun.com 2、创建配置类 package com.wym.rabbitmqprovider.utils;import org.springframework.amqp.core.…

时间序列系列03-统计模型

时间序列统计模型是用来描述和预测时间序列数据的数学模型。这些模型通常基于过去的观测值&#xff0c;并假设时间序列的行为是可预测的。以下是一些常见的时间序列统计模型&#xff1a; 1. 自回归模型&#xff08;autoregressive,AR&#xff09; 自回归&#xff08;Autoregr…

基于机器视觉的害虫种类及计数检测研究-人工智能项目-附代码

概述 农业与民生和经济发展息息相关&#xff0c;对农业发展科学化的关注既是民生需求&#xff0c; 也是经济稳步发展的迫切需求。病虫害是影响农作物生长的重要因素&#xff0c;对农作物的产量和品质都能造成无法估计的损害。 - 针对目前广大农业产区农业植保人员稀缺、病虫害…

《3D数学基础-图形和游戏开发》阅读笔记 | 3D数学基础 (学习中)

文章目录 3D数学基础矢量/向量概述 - 什么是向量单位矢量&#xff1a;只关注方向不关注大小 数学运算矢量的加法与减法减法的几何意义计算一个点到另一个点的位移矢量的点积与叉积 矩阵矩阵的几何意义 3D数学基础 矢量/向量 在笔记中 变量使用小写字母表示&#xff0c;a由于…

C++ 纯虚函数 +虚析构

抽象基类和纯虚函数 在设计时&#xff0c;常常希望基类仅仅作为其派生类的一个接口。这就是说&#xff0c;仅想对基类进行向上类型转换&#xff0c;使用它的接口&#xff0c;而不希望用户实际的创建一个基类的对象。 做到这点&#xff0c;可以在基类中加入至少一个纯虚函数(pur…