【C++】听说了吗,C++引入了四种强制类型转换

【C++】听说了吗,C++引入了四种强制类型转换
头像

⭐️个人主页:@小羊⭐️所属专栏:C++11新特性很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~

动图描述

目录


一、类型转换

1、C语言中的类型转换

如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与
接收返回值类型不一致时,就需要发生类型转化,转换的前提是类型之间有一定的关联。

  • 隐式类型转换:编译器自动进行,比如整形家族(int、char、unsigned int)/ 整型和浮点数
  • 强制类型转换:我们自己处理,比如整形和指针、指针之间
intmain(){int i =1;// 隐式类型转换double d = i;int* p =&i;// 显示的强制类型转换int address =(int)p;return0;}

2、C++中的类型转换

上面举的例子都是内置类型之间,而内置类型和自定义类型之间自定义类型和自定义类型之间都是可以通过一定的方式互相转换的。

| 内置类型和自定义类型之间:

在前面的学习中我们经常说:单参数构造函数支持隐式类型转换,多参数也可以通过加{}进行隐式类型转换。

classA{public:A(int a):_a1(a),_a2(a){}A(int a1,int a2):_a1(a1),_a2(a2){}private:int _a1;int _a2;};intmain(){ string s("Are you ok?");//隐式类型转换 A a1(1);//借助构造函数完成类型转换 A a2({1,2});return0;}
  • C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数
  • 构造函数前加explicit就不再支持隐式类型转换(但是还可以强转)

而自定义类型转换为内置类型需要通过下面这个函数:

operatorint(){//...}
  • 这个函数没有返回类型,但是有返回值
  • 函数前加explicit就不再支持隐式类型转换(但是还可以强转)
classA{public:A(int a):_a1(a),_a2(a){}A(int a1,int a2):_a1(a1),_a2(a2){}operatorint(){return _a1 + _a2;}private:int _a1;int _a2;};intmain(){ string s("Are you ok?");//隐式类型转换 A a1(1);//借助构造函数完成类型转换 A a2({1,2});int x = a1;int y = a2; cout << x << endl; cout << y << endl;return0;}

| 自定义类型和自定义类型之间:

自定义类型之间也可以借助构造函数来完成相互转换。

classA{public:A(int a):_a1(a),_a2(a){}A(int a1,int a2):_a1(a1),_a2(a2){}operatorint(){return _a1 + _a2;}intget()const{return _a1 + _a2;}private:int _a1;int _a2;};classB{public:B(int b):_b(b){}B(const A& aa):_b(aa.get()){}private:int _b;};intmain(){ A aa(1); B bb(2); bb = aa;//这里走了B的拷贝构造return0;}

例如:我们之前实现的list的迭代器有普通迭代器和const迭代器两种,普通迭代器用普通迭代器接收,const迭代器用const迭代器接收,而库中的list是支持普通迭代器用const迭代器接收的,那我们也可以给自己的list加上这个功能。

在这里插入图片描述

增加一个用于类型转换的构造函数:

//...ListIterator(const ListIterator<T, T&, T*>& it):_node(it._node){}//...
注意:这里的参数一定是写死的,不能是const ListIterator<T, Ref, Ptr>& it

3、C语言类型转换的缺陷

  1. 转换的可视性差,所有的转换形式都是以一种相同的形式书写,难以跟踪错误的转换
  2. 隐式类型转换有些情况下可能会出现问题,比如数据精度丢失
  3. 显示类型转换将所有情况混在一起,代码不够清晰

4、C++中的四种强制类型转换

标准C++为了加强类型转换的可视性,引入了下面四种命名的强制类型转换操作符。主要是为了让类型转换有统一的规范,更加严谨。

4.1 static_cast

static_cast用于非多态类型的转换(对应隐式类型转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。

intmain(){double d =3.14;int a =static_cast<int>(d); cout << a << endl;return0;}

4.2 reinterpret_cast

reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型(对应强制类型转换)。

intmain(){double d =3.14;int a =static_cast<int>(d); cout << a << endl;//这里使用static_cast会报错,应该使用reinterpret_cast//int *p = static_cast<int*>(a);int* p =reinterpret_cast<int*>(a); cout << p << endl;return0;}

4.3 const_cast

const_cast最常用的用途就是删除变量的const属性对应强制类型转换中有风险的去掉const属性),方便赋值。

intmain(){constint a =2;int* p =const_cast<int*>(&a);*p =3; cout << a << endl;}
在这里插入图片描述

使用volatile可以确保编译器不会对这些变量的访问进行优化,从而确保每次访问都能读取到最新的值。

在这里插入图片描述

4.4 dynamic_cast

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

  • 向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
  • 向下转型:父类对象指针/引用->子类指针/引用(dynamic_cast转型是安全的)

注意:

  1. dynamic_cast只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回nullptr
classA{public:virtualvoidf(){}};classB:publicA{};voidfun(A* pa){// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回 B* pb1 =static_cast<B*>(pa); B* pb2 =dynamic_cast<B*>(pa); cout <<"pb1:"<< pb1 << endl; cout <<"pb2:"<< pb2 << endl;}intmain(){ A a; B b;fun(&a);fun(&b);return0;}
在这里插入图片描述

dynamic_cast 作用于普通指针或引用,用于将基类指针(或引用)转换为派生类指针(或引用) 。

另外还有 dynamic_pointer_cast,专门用于智能指针的类型转换 ,将一个基类智能指针转换为派生类智能指针 。

二者都在运行时进行类型检查以确保转换安全性。


本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~

头像

Read more

【Linux】Linux基本使用和程序部署

【Linux】Linux基本使用和程序部署

🎬 那我掉的头发算什么:个人主页 🔥 个人专栏: 《javaSE》《数据结构》《数据库》《javaEE》 ⛺️待到苦尽甘来日 文章目录 * Linux环境搭建 * 环境搭建方式 * 使用云服务器 * 使用终端软件连接到Linux * Linux常用命令 * ls * pwd * cd * touch * cat * mkdir * rm * cp * mv * tail * vim * grep * ps * netstat * 搭建java部署环境 * apt * JDK * MYSQL * 部署web项目到Linux * 什么是部署 * 环境配置 * 构建项目并打包 * 上传jar包运行程序 * 杀死进程 Linux环境搭建 环境搭建方式 主要有四种: 1. 直接安装在物理机上。但是 Linux 桌面使用起来非常不友好。所以不建议。【不推荐】。 2. 使用虚拟机软件,

By Ne0inhk
Flutter 三方库 coverage_reporter 的鸿蒙化适配指南 - 实现具备 LCOV 自动分析与多格式统计的代码覆盖率报告引擎、支持端侧质量量化与 CI 流水线对齐实战

Flutter 三方库 coverage_reporter 的鸿蒙化适配指南 - 实现具备 LCOV 自动分析与多格式统计的代码覆盖率报告引擎、支持端侧质量量化与 CI 流水线对齐实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 coverage_reporter 的鸿蒙化适配指南 - 实现具备 LCOV 自动分析与多格式统计的代码覆盖率报告引擎、支持端侧质量量化与 CI 流水线对齐实战 前言 在进行 Flutter for OpenHarmony 的企业级应用交付时,如何客观地衡量测试用例的完备性?“代码覆盖率(Code Coverage)”是唯一的硬指标。虽然 Dart SDK 可以导出原始的 coverage 数据,但如何将其转化为直观、可读且能集成到工作流中的美观报告?coverage_reporter 是一款专为 Dart 项目设计的覆盖率报告聚合工具。本文将介绍如何在鸿蒙端构建极致、透明的质量度量底线。 一、原直观解析 / 概念介绍 1.1 基础原理 该库建立在“

By Ne0inhk
树莓派5-ollama-linux-arm64.tgz 下载

树莓派5-ollama-linux-arm64.tgz 下载

1.下载 由于官方下载速度太慢且容易失败,我这里上传了一份到云盘供大家下载: 通过网盘分享的文件:ollama-linux-arm64.tgz 链接: https://pan.baidu.com/s/1tx_OPpl-8O2HJfXlP4tXTg?pwd=ffwx 提取码: ffwx --来自百度网盘超级会员v4的分享 2.安装启动  将下载好的包上传到树莓派指定目录并解压,例如我这里解压到了: sudo tar -C /usr/local/bin -xzf ollama-linux-arm64.tgz 3.验证安装 ollama --version 4.手动启动测试 ollama serve 如果出现如下图类似的信息表示启动成功: 5.设置开机自启 sudo nano /etc/systemd/system/ollama.

By Ne0inhk
Flutter 三方库 metalink_advanced_final 的鸿蒙化适配指南 - 在 OpenHarmony 打造极致、安全的 P2P 下载与资源分发底座

Flutter 三方库 metalink_advanced_final 的鸿蒙化适配指南 - 在 OpenHarmony 打造极致、安全的 P2P 下载与资源分发底座

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 metalink_advanced_final 的鸿蒙化适配指南 - 在 OpenHarmony 打造极致、安全的 P2P 下载与资源分发底座 在大数据传输、大型游戏资源更新以及分布式固件升级场景中,传统的单点 HTTP 下载往往面临带宽压力和校验失效的风险。metalink 协议(RFC 5854)通过整合多个源地址与强校验机制,提供了一套工业级的资源分发方案。metalink_advanced_final 库为 Flutter 开发者提供了该协议的终极解析与执行引擎。本文将深度解析如何在 OpenHarmony(鸿蒙)环境下,结合鸿蒙的并发架构,完美适配这一强大的下载工具。 前言 随着鸿蒙系统(HarmonyOS)跨终端特性的普及,应用在不同设备间流转时的资源同步速度成为了用户体验的“胜负手”。metalink_advanced_final

By Ne0inhk