04 C++中的四种强制类型转换
系列文章目录
04 C++中的四种强制类型转换
目录
系列文章目录
文章目录
前言
一、静态转换(Static Cast)
二、动态转换(Dynamic Cast)
三、常量转换(Const Cast)
四、重新解释转换(Reinterpret Cast)
总结
前言
类型转换是将一个数据类型的值转换为另一种数据类型的值。
C++ 中有四种类型转换:静态转换、动态转换、常量转换和重新解释转换。
隐式类型转换是编译器自动隐式进行的,需要在代码中体现,而显示类型转换由程序员明确指定。
C++支持C风格的强制转换,但是C风格的强制转换可能带来一些隐患,让一些问题难以发现。
所以C++提供了一组适用于不同场景的强制转换的函数:
- static_cast
- dynamic_cast
- const_cast
- reinterpret_cast
下面对这四种转换操作的适用场景分别进行说明。
一、静态转换(Static Cast)
静态转换是将一种数据类型的值强制转换为另一种数据类型的值。
静态转换通常用于比较类型相似的对象之间的转换,例如将 int 类型转换为 float 类型。
静态转换不进行任何运行时类型检查,因此可能会导致运行时错误。
下面是一个例子,将int类型转换为float类型:
int main()
{int a = 10;float b = static_cast<float>(a); // 静态将int类型转换为float类型cout << typeid (a).name() << endl;cout << typeid (b).name() << endl;}
输出结果为:
int
float
需要注意的是,这里,即使我们写int a = 'a';程序也可以编译过去,所以我们要注意使用。
二、动态转换(Dynamic Cast)
C++中的动态转换(dynamic_cast)是一种类型转换运算符,用于在运行时将指向父类的指针或引用转换为指向其派生类的指针或引用。
使用动态转换时,必须满足以下两个条件之一:
- 目标类型是源类型的公共派生类。
- 源类型是指向目标类型的指针或引用。
如果以上条件不满足,则转换将失败并返回空指针或引用。
下面是一个示例:
#include <iostream>
using namespace std;class Animal {
public:virtual void makeSound() {cout << "Unknown animal sound." << endl;}
};class Cat : public Animal {
public:void makeSound() {cout << "Meow!" << endl;}
};class Dog : public Animal {
public:void makeSound() {cout << "Woof!" << endl;}
};int main() {// 两个指针变量 a 和 b 分别指向一个 Cat 类型对象和一个 Dog 类型对象。Animal* a = new Cat;Animal* b = new Dog;// 使用动态类型转换将指针 a 转换为指向 Cat 类型的指针 c。Cat* c = dynamic_cast<Cat*>(a);// 判断指针 c 是否为 nullptr,如果不是,则调用 Cat 类的成员函数 makeSound() 输出动物的叫声;// 否则输出 “Cannot convert Animal* to Cat*.”。if (c) {c->makeSound();}else {cout << "Cannot convert Animal* to Cat*." << endl;}// 使用动态类型转换将指针 b 转换为指向 Cat 类型的指针 c。c = dynamic_cast<Cat*>(b);if (c) {c->makeSound();}else {cout << "Cannot convert Animal* to Cat*." << endl;}return 0;
}
输出结果为:
Meow!
Cannot convert Animal* to Cat*.
在此示例中,我们创建了两个Animal类型的指针,一个指向Cat对象,另一个指向Dog对象。接下来,我们使用Dynamic Cast将这些指针转换为指向Cat对象的指针。第一个转换将成功,因为指针a指向的是Cat对象。第二个转换失败,因为指针b指向的是Dog对象,无法转换为Cat对象。
注意:动态转换在代码中经常用于将基类对象转换为派生类对象,以便使用派生类的成员函数和成员变量。需要注意的是,使用动态转换时应该注意类型安全,并避免滥用。
三、常量转换(Const Cast)
常量转换用于将 const 类型的对象转换为非 const 类型的对象。
常量转换只能用于转换掉 const 属性,不能改变对象的类型
下面是一个常量转换(const_cast)的代码示例:
#include <iostream>
using namespace std;void printValue(int value) {cout << "The value is: " << value << endl;
}int main() {const int value = 10;const int* ptr = &value;// 将 ptr 转换为非常量指针int* mutablePtr = const_cast<int*>(ptr);// 修改指针所指向的值*mutablePtr = 20;// 调用函数输出修改后的值printValue(value);return 0;
}
在这个示例中,我们首先定义了一个常量值 value 和一个指向该值的常量指针 ptr。然后,我们使用 const_cast 将 ptr 转换为非常量指针 mutablePtr。接着,我们通过 mutablePtr 修改了指针所指向的值为 20。最后,我们调用函数 printValue 输出修改后的值,即 20。
需要注意的是,这里的常量指针指向的值并没有真正变为可修改的,只是通过 const_cast 绕过了编译器的常量性检查。因此,使用 const_cast 必须非常小心,避免对常量值进行意外的修改。
四、重新解释转换(Reinterpret Cast)
C++中的重新解释转换(Reinterpret Cast)是一种类型转换操作,用于将一个指针或引用转换为另一种不同类型的指针或引用,而不考虑它的原始类型和值。它主要用于将一个对象的位模式重新解释为另一个对象的位模式。由于这种类型转换没有进行类型检查,因此使用起来比较危险,应该谨慎使用。
以下是一个重新解释转换(reinterpret_cast)的代码:
#include <iostream>
using namespace std;int main() {int num = 100;double* pDouble = reinterpret_cast<double*>(&num);cout << "num = " << num << endl;cout << "pDouble = " << *pDouble << endl;return 0;
}
在这个例子中,我们将一个整数类型的变量num的地址,强制类型转换为了双精度浮点数类型的指针。这个强制类型转换的意义是告诉编译器将num的二进制数据按照双精度浮点数类型的格式重新解释。
当我们输出pDouble的值时,由于在编译器中整数和浮点数的存储方式一般是不同的,因此pDouble的值很可能会是随机垃圾数据。
因此,我们在实际开发中很少使用reinterpret_cast,除非我们确实需要进行一些非常特殊的操作。
总结
综上,在使用强制类型转换时,需要首先考虑清楚使用目的:
- static_cast:基本类型转换,低风险;
- dynamic_cast:类层次间的上行转换或下行转换,低风险;
- const_cast:去 const 属性,低风险;
- reinterpret_cast:转换不相关的类型,高风险。
相关文章:
04 C++中的四种强制类型转换
系列文章目录 04 C中的四种强制类型转换 目录 系列文章目录 文章目录 前言 一、静态转换(Static Cast) 二、动态转换(Dynamic Cast) 三、常量转换(Const Cast) 四、重新解释转换(Reinte…...
电力感知边缘计算网关产品设计方案-边缘计算自控算法模型
边缘计算网关与其他数据采集的IoT网关设备不同之处在于可以根据应用场景和产品解决方案,单独设置一些边缘计算算法模型,实现离线系统和边缘计算自控逻辑判别+执行系统方案,自控算法逻辑单元也是边缘计算网关自控系统方案的核心单元。 自控算法逻辑单元根据产品应用不同,有…...
C语言进阶之笔试题详解(1)
引言: 对指针知识进行简单的回顾,然后再完成笔试题。 ✨ 猪巴戒:个人主页✨ 所属专栏:《C语言进阶》 🎈跟着猪巴戒,一起学习C语言🎈 目录 引言: 知识简单回顾 指针是什么 指针变…...
报道|2023 INFORMS 最佳论文(部分)华人获奖者名单
编者按 本文收集了部分2023年INFORMS年会最佳论文评选的华人获奖者名单,祝贺获奖者们!如果读者身边有本文遗漏的获奖者请在文章下方评论区告诉小编。 ● George Nicholson学生论文竞赛一等奖: Bayesian Design Principles for Frequentist …...
【Docker】从零开始:12.容器数据卷
【Docker】从零开始:12.容器数据卷 1.什么是容器数据库卷2.数据的覆盖问题3.为什么要用数据卷4.Docker提供了两种卷:5.两种卷的区别6.bind mount7.Docker managed volumevolume 语法volume 操作参数 1.什么是容器数据库卷 卷 就是目录或文件,…...
Spring Boot 整合MyBatis-Plus 详解
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 全新的 MyBatis-Plus 3.0 版本基于 JDK8,提供了 lambda 形…...
【前端】让列表像Excel单元格一样编辑
前言 领导说了一堆的话,最后总结一句就是客户很懒,客户的员工更加懒。 本着让别人节省时间的原则,提倡出了让列表和Excal的单元格一样,不仅看数据还可以随时更改数据。 查资料 根据 Jeecg-Vue3 源码介绍,从而知道是基于 Vben Admin 开源项目进行改造的。 因此在 Vben…...
数字图像处理-Matlab实验
实验一 图像增强 实验内容: 对于给定的低对比度测试图像,利用灰度图像直方图均衡化算法进行图像视觉效果增强。 对于给定的低照度彩色测试图像,结合颜色空间转换和灰度图像直方图均衡化算法进行图像视觉效果增强。 实验数据: Test1_1.jpg: Test1_2.jpg: 实验步骤: %% …...
Nginx:配置文件详解
一、Nginx配置文件 main配置段:全局配置 events段:定义event工作模式 http {}:定义http协议配置 支持使用变量: 内置变量:模块会提供内建变脸定义 自定义变量:set var_name value 二、 主…...
卷积,是什么?
其实就是对事物的作用,或者说作用力,比如说,石板上没有字,我们刻上字,便于识别,从机器视觉角度来说,就是对图像的作用力,这种作用使得能看清想要的东西,感觉还是很主观&a…...
Javascript的闭包有哪些应用?
JavaScript 中的闭包是一种强大的特性,它可以用于多种应用。以下是一些闭包在 JavaScript 中的常见应用: 1、封装私有变量: 通过闭包,可以创建私有变量和方法。外部作用域无法直接访问闭包内的变量,从而实现了信息隐藏…...
LCM-LoRA模型推理简明教程
潜在一致性模型 (LCM) 通常可以通过 2-4 个步骤生成高质量图像,从而可以在几乎实时的设置中使用扩散模型。 来自官方网站: LCM 只需 4,000 个训练步骤(约 32 个 A100 GPU 小时)即可从任何预训练的稳定扩散 (SD) 中提取出来&#…...
设计模式-开篇
什么是设计模式 设计模式是一种被反复使用、多数人知晓的、经过分类编目的代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、提高代码的可靠性。设计模式不是可直接转化为代码的完成解决方案,而是描述了如何解决一个问题的经过…...
HashMap的实现原;HashMap的工作原理;HashMap存储结构; HashMap 构造函数
文章目录 说一下HashMap的实现原理(非常重要)①HashMap的工作原理HashMap存储结构常用的变量HashMap 构造函数tableSizeFor() put()方法详解hash()计算原理resize() 扩容机制get()方法为什么HashMap链表会形成死循环 HashMap是我们在工作中使用到存储数据特别频繁的数据结构&am…...
JavaScript 原型,原型链的特点
JavaScript 的原型(Prototype)和原型链(Prototype chain)是 JavaScript 面向对象编程中的重要概念。 原型(Prototype) 在 JavaScript 中,每个对象都有一个原型对象,而这个原型对象…...
越南服务器租用:企业在越南办工厂的趋势与当地(ERP/OA等)系统部署的重要性
近年来,越南逐渐成为全球企业布局的热门目的地之一。许多企业纷纷选择在越南设立工厂,以利用其低廉的劳动力成本和优越的地理位置。随着企业在越南的扩张,对于当地部署ERP系统或OA系统等的需求也日益增长。在这种情况下,租用越南服…...
Qt QString与QChar总结
(一) QString 1 QString的简介 QString 是Qt 中的一个类,用于存储字符串,QString 没有父类。QString 存储的是一串字符,每个字符是一个 QChar 类型的数据。QChar 使用的是 UTF-16 编码,一个字符包含 2字节数据。 对于超过 6553…...
Leetcode算法系列| 1. 两数之和(四种解法)
目录 1.题目2.题解解法一:暴力枚举解法二:哈希表解法解法三:双指针(有序状态)解法四:二分查找(有序状态) 1.题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数…...
汇编-pop出栈指令
32位汇编 执行动作分为两步: 第一步:读出数据 第二步:改变栈地址 如果操作数是16位, 则ESP加2; 如果操作数是32位, 则ESP加4 espesp2 或 espesp4 格式:...
【代码】基于VMD(变分模态分解)-SSA(麻雀搜索算法优化)-LSTM的光伏功率预测模型(完美复现)matlab代码
程序名称:基于VMD(变分模态分解)-SSA(麻雀搜索算法优化)-LSTM的光伏功率预测模型 实现平台:matlab 代码简介:提出了变分模态分解(VMD)和麻雀搜索算法(SSA)与长短期记忆神经网络 (LSTM)相耦合,…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...
