27.C++的类型转换(介绍了static_cast、reinterpret_cast、const_cast、dynamic_cast的用法)

1. C语言中的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败

  2. 显式类型转化:需要用户自己处理

void Test ()
{int i = 1;// 隐式类型转换double d = i;printf("%d, %.2f\n" , i, d);int* p = &i;// 显示的强制类型转换int address = (int) p;printf("%x, %d\n" , p, address);
}

缺陷:转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换

C风格的转换格式很简单,但是有不少缺点的:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失

  2. 显式类型转换将所有情况混合在一起,代码不够清晰

    因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的转化风格。

2. C++强制类型转换

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:

static_cast、reinterpret_cast、const_cast、dynamic_cast

2.1 static_cast、reinterpret_cast、const_cast

#include<iostream>using namespace std;int main()
{// 情况1:int i = 1;// C++规范转换 -- static_cast适用相似类型的转换(这些类型的表示意义差不多)// 如下,将int类型转化为double类型double d = static_cast<double>(i);printf("%d, %.2f\n", i, d);// 打印结果为// 1// 1.00// 情况2:int* p = &i;// int* 是地址, int是整型,因此不是相似类型,也就不能够使用static_cast// C++规范转换 --reinterpret_cast适用于不相关的类型之间的转换// reinterpret v.重新解释// 如下将int*类型转化为int类型int address = reinterpret_cast<int>(p);printf("%x, %d\n", p, address);// 打印结果为// 56f9a8// 5700008// 情况3:// C++规范转换 -- const_cast 去掉const属性。单独分出来,警示你这个很危险,用的时候谨慎一点const int a = 2;// 如下,去掉了&a的const属性int* p1 = const_cast<int*>(&a);*p1 = 3; // 将a内存中对应的值修改为3cout << a << endl;   cout << *p1 << endl;// 打印结果为// 2// 3// 为什么a和*p1打印的结果不一致呢?// 这是因为a的类型为const int,编译器默认a是不会被改变的// 因此将a的值,直接拿到了寄存器来使用,不再到内存中读取a的值(这是一种编译器的优化),打印a时,打印的是寄存器中的值// 而*p1指向的是a内存中的位置,打印的a内存对应的值// 情况4:// 使用关键词volatile,编译器就不会进行优化,读取a时,会到内存中进行读取,而不是在寄存器中读取// volatile  /ˈvɑːlət(ə)l/  adj.易变的// 使用关键词修饰volatile,那么编译器就不会进行优化volatile const int a1 = 2;int* p2 = const_cast<int*>(&a1);*p2 = 3;cout << a1 << endl;   cout << *p2 << endl;// 打印结果为// 3// 3return 0;
}

2.2 dynamic_cast

dynamic_cast用于将一个基类对象的指针/引用转换为派生类对象的指针或引用(动态转换)

向上转型:派生类类对象指针/引用->基类指针/引用(不需要转换,赋值兼容规则)

向下转型:基类对象指针/引用->派生类指针/引用(用dynamic_cast转型是安全的)

注意:

  1. dynamic_cast只能用于基类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0
  • 错误演示
#include<iostream>using namespace std;// 基类
class A
{
public:virtual void f() {}int _a = 0;
};// 派生类
class B : public A
{
public:int _b = 0;
};void Func(A* ptr)
{// 直接转换是不安全的// 当ptr指向的是派生类对象B时,那么派生类对象转为派生类对象是没有什么问题的// 当ptr指向的是基类对象A时,那么基类对象转为派生类对象存在越界风险// _b是属于派生类对象B,如果将基类对象转为子类对象,那么基类对象也可以访问到_b,这就造成了越界,是不安全的B* bptr = (B*)ptr;cout << bptr << endl;bptr->_a++;bptr->_b++;cout << bptr->_a << endl;cout << bptr->_b << endl;
}int main()
{A aa;B bb;Func(&aa);Func(&bb);return 0;
}
  • 使用dynamic_cast进行转换
#include<iostream>
using namespace std;// 基类
class A
{
public:virtual void f() {}int _a = 0;
};// 派生类
class B : public A
{
public:int _b = 0;
};void Func(A* ptr)
{// C++规范的dynamic_cast是安全的// 如果ptr是指向基类,则转换失败,返回空// 如果ptr是指向派生类,则转换成功B* bptr = dynamic_cast<B*>(ptr);cout << bptr << endl;// 当bptr不为空,说明是派生类转派生类,转换成功// 当bptr为空,说明是基类转派生类,转换失败,此处进行判断,避免越界,保证安全访问if (bptr){bptr->_a++;bptr->_b++;cout << bptr->_a << endl;cout << bptr->_b << endl;}
}int main()
{A aa;B bb;Func(&aa);Func(&bb);return 0;
}

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

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

相关文章

JavaScript中的call、apply和bind方法(2)

JavaScript中的call、apply和bind方法是用于改变函数执行上下文和预先设置参数的强大工具。它们在编写可维护和优雅的代码时起到了重要的作用。本文将介绍这些方法的原理和使用场景&#xff0c;并展示如何将它们应用于你的代码中&#xff0c;使其更加漂亮。 call方法的原理和使…

STM32 CANFD 基础知识留档

讲得比较细的文章但可能有问题自行判定 附1 附2 前言 CAN2.0 协议中数据段波特率和仲裁段波特率默认是一致&#xff0c;因此只需要关注传输波特率即可 CANFD 协议是向下兼容 CAN2.0 的数据通讯&#xff0c;因此实际使用中需要配置 STM32H7 系列支持的标准是 Compliant with …

大语言模型中上下文长度扩展技术的内容、原因和方式-综述

24年1月阿联酋科技创新研究院、孟加拉国伊斯兰科技大学、斯坦福大学、亚马逊公司和南卡大学AI研究院的论文“The What, Why, and How of Context Length Extension Techniques in Large Language Models – A Detailed Survey“。 LLM通常面临上下文长度外推方面的限制。 理解…

C++11 线程池:轻量级高并发解决方案

C11 线程池&#xff1a;轻量级高并发解决方案 线程池&#xff08;Thread Pool&#xff09;是一种线程管理的机制&#xff0c;它包含了多个预先创建的线程&#xff0c;用于执行多个任务&#xff0c;这些任务被放入任务队列中等待执行。 满足我们的生产者和消费者模型。 线程…

一文带你快速了解GPT-4o!内含免费使用指南!

一、GPT-4o简介 北京时间5月14日&#xff0c;OpenAI举行春季发布会。OpenAI在活动中发布了新旗舰模型“GPT-4o”&#xff01;据OpenAI首席技术官穆里穆拉蒂&#xff08;Muri Murati&#xff09;介绍&#xff0c;GPT-4o在继承GPT-4强大智能的同时&#xff0c;进一步提升了文本、…

常用限流方式

1. 令牌桶算法&#xff08;Token Bucket&#xff09; 令牌桶算法是一种常用的限流算法&#xff0c;它通过维护一个固定容量的令牌桶&#xff0c;以限制单位时间内通过的请求数量。当请求到达时&#xff0c;会从令牌桶中获取一个令牌&#xff0c;如果令牌桶中没有令牌&#xff…

如何使用Python进行网页爬取

Python爬虫案例可以有很多种&#xff0c;但我会为你提供一个简单的案例&#xff0c;该案例使用Python的requests库来爬取一个网页的内容&#xff0c;并使用BeautifulSoup库来解析HTML并提取特定的信息。 假设我们要从某个新闻网站&#xff08;例如&#xff1a;示例网站&#x…

电力场景设备漏油检测数据集VOC+YOLO格式338张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;338 标注数量(xml文件个数)&#xff1a;338 标注数量(txt文件个数)&#xff1a;338 标注类别…

第N1周:one-hot编码

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 1.什么是one-hot编码 One-Hot编码是一种常用于机器学习中的特征编码方式&#xff0c…

Qt---项目的创建及运行

一、创建第一个Qt程序 1. 点击创建项目后&#xff0c;选择项目路径以及给项目起名称 名称&#xff1a;不能有中文、不能有空格 路径&#xff1a;不能有中文路径 2. 默认创建有窗口类myWidget&#xff0c;基类有三种选择&#xff1a;QWidget、QMainWindow、QDialog 3. m…

Redis为什么快

用了那么久的redis&#xff0c;突然意识到这个问题答不上来&#xff0c;只知道内存数据库&#xff0c;内存的读写性能快于磁盘。 1. 内存存储 Redis 是一个基于内存的数据库&#xff0c;它将所有的数据都保存在内存中&#xff0c;这使得读取的速度非常快。内存读写速度远超于…

#自学习# 记一次py脚本打开浏览器页面

在项目总结中&#xff0c;遇到系统后台利用浏览器拉起一个已知路径页面的需求&#xff0c;趁着机会整理下。实现起来比较简单&#xff0c;浏览器默认谷歌。 一、技术原理 Selenium&#xff1a;Selenium 是一个用于自动化 Web 浏览器的工具&#xff0c;可模拟用户在浏览器中的各…

socket接口定义范围及操作

Socket接口&#xff0c;也称为套接字接口&#xff0c;是用于实现网络通信的一种编程接口。它定义了一系列的操作和函数&#xff0c;允许应用程序通过网络进行数据传输。 Socket接口不仅仅局限于特定的操作系统或网络协议&#xff0c;而是在多种网络环境中通用&#xff0c;包括但…

Python面试题【数据结构和算法部分101-130】

Python面试题【数据结构和算法部分101-130】 Python面试题【数据结构和算法部分101-130】 Python面试题【数据结构和算法部分101-130】 问题&#xff1a;如何在Python中实现二分查找&#xff1f; 答案&#xff1a; def binary_search(arr, target):low, high 0, len(arr) - 1…

奔向光明阿波罗(五)

下半场的艰难曙光 有“中国无人驾驶黄埔军校”之称的百度&#xff0c;最初的雄心是给未来的智能汽车安上一颗“百度之心”&#xff0c;取得类似于“Intel Inside“的品牌强强联合效果。阿波罗希望为汽车行业的玩家提供一个“开放、完整、安全”的开源平台&#xff0c;帮助他们结…

正则表达式中的$分组使用示例

正则表达式中的 $ 符号通常用于表示字符串的结束位置&#xff0c;但当你在替换操作或者某些特殊上下文中提到 $ 后跟数字&#xff08;如 $1, $2, etc.&#xff09;&#xff0c;这并不表示结束位置&#xff0c;而是引用之前正则表达式捕获组的内容。 以下是使用 $ 引用捕获组的…

计算机视觉与深度学习实战:以Python为工具,基于块匹配的全景图像拼接

注意:本文的下载教程,与以下文章的思路有相同点,也有不同点,最终目标只是让读者从多维度去熟练掌握本知识点。 下载教程:计算机视觉与深度学习实战-以MATLAB和Python为工具_基于块匹配的全景图像拼接_项目开发案例教程.pdf 计算机视觉作为人工智能领域的一个重要分支,旨在…

成都百洲文化传媒有限公司怎么样?靠谱吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业正以前所未有的速度蓬勃发展。作为这一变革的积极参与者和推动者&#xff0c;成都百洲文化传媒有限公司以其专业的电商服务&#xff0c;正逐渐成为行业内的佼佼者。 一、公司简介 成都百洲文化传媒有限公司自成立以来&#xff…

邦芒宝典:离职前一定要做的几件事帮你刷爆好感

​​这个问题&#xff0c;关键还是要看这位有本事的员工的职业素养如何。虽说工有本事的员工往往都会具备比较高的职业素养&#xff0c;比如强专业能力、强沟通、强执行、正确的价值观与职业操守等等&#xff0c;但也可能有些人能力是不错&#xff0c;但素养比较低&#xff0c;…

MyBatis的创建和测试

创建项目点击Spring Initializr然后点击next 点击SQL 选择里面的Mybatis Framework和Mysql Driver 按如下图片创建项目 user表中的数据 #下面这些内容是为了让MyBatis映射 #指定Mybatis的Mapper文件 mybatis.mapper-locationsclasspath:mappers/*xml #指定Mybatis的实体目录 my…