当前位置: 首页 > news >正文

C++进阶 类型转换

本文简介:介绍C++中类型转换的方式

类型转换

    • C语言中的类型转换
    • 为什么C++需要四种类型转换
    • C++强制类型转换
      • static_cast
      • reinterpret_cast
      • const_cast
      • dynamic_cast
    • RTTI(了解)
    • 总结

C语言中的类型转换

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

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
  2. 显式类型转化:需要用户自己处理

隐式类型转换

   int i = 1;double d = i;

显式类型转换

    int*p = &i;int address = (int)p; 

而C++是C语言的超集 自然也能做到上面的两种类型转化

但是上面的两种类型转换有一种缺点

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

为什么C++需要四种类型转换

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

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

比如说下面这段代码

int end = 3;
size_t pos = 0;
while (1)
{ if (end >= pos){end--;}
}

上面的这段代码会进入死循环 因为在进行比较运算符运算的时候end发生了隐式类型转化
变成了size_t 类型 从此以后不会出现小于0的数了

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

C++强制类型转换

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

static_cast、reinterpret_cast、const_cast、dynamic_cast

static_cast

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

我们可以简单理解为是隐式类型转换 代码使用如下

int main()
{double d = 12.34;int a = static_cast<int>(d);cout<<a<<endl;return 0;
}

reinterpret_cast

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

我们可以简单理解为类型不相关的数据就可以使用 代码表示如下

int main()
{double d = 12.34;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);return 0;
}

const_cast

const_cast最常用的用途就是删除变量的const属性 方便赋值

我们可以写出以下代码

#include <iostream>    
using namespace std;    int main()    
{    const int a = 2;    int* p = const_cast<int*>(&a);    *p = 3;    cout << a << endl;    cout << *p << endl;                                                                                                           return 0;    
} 

此时我们就可以通过p地址的解引用来改变该地址的值

那么大家可以猜猜看最后的结果是什么呢?

在这里插入图片描述
答案是2 3 是不是出乎大家的意料了

这是因为g++编译器认为 a是一个常量 我们不会去轻易修改它 所以说将a的值放在了寄存器当中 读取a的数据也会从寄存器中读

所以说尽管a这个变量的地址中的值被修改成3了 我们读取仍然会是2

那么有没有什么办法可以优化呢?

当然有 我们只需要让这个变量不出现在寄存器当中就可以了 我们可以使用volatile关键字修饰a变量 这样子a变量就不会出现在寄存器当中了 代码和演示结果如下

 volatile const int a = 2; 

在这里插入图片描述

dynamic_cast

我们在之前的内容中学习过 大部分的类型转换都是经过临时变量的 就比如说下面的代码

int a = 0;
double b = a;

这中间并不是直接将a赋值给b 而是会经历一个临时变量

在这里插入图片描述

这也就是为什么我们double类型的引用并不能直接引用int类型的数据 因为我们引用的实际上是一个临时变量 而临时变量具有常属性 必要要用const修饰才行 否则会产生一个权限扩大的问题

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

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

在C++中 子类对象的指针或者引用给父类指针或者引用的时候是不会经过类型转换的 因为这实际上就是一个切片 这是C++规则所允许的 (关于切片在我的继承博客那一章有讲解)

而向下转型 即父类对象指针/引用->子类指针/引用则是要经过类型转换的

首先我们要理解第一个点 父类的对象不管怎么样是绝对不被允许转化为子类对象的 只有指针和引用可以转

其实父类对象的指针有可能是指向父类的 也有可能是指向子类的

拿下面的两个类来举例说

class A
{
public:virtual void P(){;}
private:int _a = 1;
};class B  : public A
{
private:int _b = 2;
};

父类是A 子类是B

void Test(A* pa)
{B* pb1 = dynamic_cast<B*>(pa);cout << pb1 << endl;
}int main()
{A* pa = new A;B* pb = new B;Test(pa);Test(pb);return 0;
}

我们定义了一个父类指针 一个子类指针 并且将他们都传入到一个Test函数中去 子类的指针会被转化为父类的指针

但是我们需要知道的一点是 :父类的范围一定是小于等于子类的范围的

在这里插入图片描述

也就是说 父类的指针如果它本来是就是子类的 那么转化为子类指针之后正常的操作没有问题

但是如果说 父类指针本来就是指向父类的 那么转化为子类指针之后就有可能会出现越界问题

所以说为了解决指针越界问题 我们的dynamic_cast函数会先进行判断

如果该父类指针本来是指向子类的 那么可以成功转换 反之则返回一个空指针

运行结果如下

在这里插入图片描述

注意:

  1. dynamic_cast只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0
  3. dynamic_cast相比于原来的强制类型转换是一种更加安全的转换方式

所以说dynamic_cast最大作用还是用来区分指针到底是指向父类还是指向子类

如果是指向父类的就返回空 如果是指向子类的就可以转

面试题

四种类型转换分别是什么
static_cast reinterpret_cast const_cast dynamic_cast

他们的应用场景分别是什么

  • static_cast 隐式类型转换
  • reinterpret_cast 强制类型转换
  • const_cast const修饰取消
  • dynamic_cast 父类指针/引用转子类指针/引用

RTTI(了解)

RTTI:Run-time Type identification的简称,即:运行时类型识别。

C++通过以下方式来支持RTTI:

  1. typeid运算符 获取变量类型
  2. dynamic_cast运算符 获取父类指针指向父类还是子类
  3. decltype 推导函数类型

总结

在这里插入图片描述

相关文章:

C++进阶 类型转换

本文简介&#xff1a;介绍C中类型转换的方式 类型转换 C语言中的类型转换为什么C需要四种类型转换C强制类型转换static_castreinterpret_castconst_castdynamic_cast RTTI&#xff08;了解&#xff09;总结 C语言中的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型…...

Idea中隐藏指定文件或指定类型文件

Setting ->Editor ->Code Style->File Types → Ignored Files and Folders输入要隐藏的文件名&#xff0c;支持*号通配符回车确认添加...

第2步---MySQL卸载和图形化工具展示

第2步---MySQL卸载和图形化工具展示 1.MySQL的卸载 2.MySQL的图形化工具 2.1常见的图形化工具 SQLyog&#xff1a;简单。SQLyog首页、文档和下载 - MySQL 客户端工具 - OSCHINA - 中文开源技术交流社区 Mysql Workbench &#xff1a;MySQL :: MySQL Workbench DataGrip&…...

原型和原型链

好久没记了有点忘记了&#xff0c;来记录一下。 1、函数和对象的关系&#xff1a;对象都是通过函数创建的&#xff0c;函数也是一个对象。 2、原型和原型链 1.原型&#xff1a;原型分为两种 prototype&#xff1a;每一个函数都会有prototype属性&#xff0c;它指向函数的原型…...

解决ios隔空播放音频到macos没有声音的问题

解决ios隔空播放音频到macos没有声音的问题 一、检查隔空播放支持设备和系统要求二、打开隔空播放接收器三、重置MAC控制中心进程END 一、检查隔空播放支持设备和系统要求 Mac、iPhone、iPad 和 Apple Watch 上“连续互通”的系统要求 二、打开隔空播放接收器 ps;我设备是同一…...

LTPP在线开发平台【使用教程】

LTPP在线开发平台 点击访问 LTPP在线开发平台 LTPP&#xff08;Learning teaching practice platform&#xff09;在线开发平台是一个编程学习网站&#xff0c;该网站集文章学习、短视频、在线直播、代码训练、在线问答、在线聊天和在线商店于一体&#xff0c;专注于提升用户编…...

0818 新增码表 git拉取代码

目的是新增两个码表字段。然后和前端联调。 use db; delete from sys_dict_data where dict_type res_switch_status; INSERT INTO sys_dict_data VALUES (0, 1, 已接入, 1, res_switch_status, NULL, default, N, 0, , 2022-07-26 10:43:41, , NULL, NULL); INSERT INTO sys…...

AI 绘画Stable Diffusion 研究(十)sd图生图功能详解-精美二维码的制作

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 为了让大家更直观的了解图生图功能&#xff0c;明白图生图功能到底是干嘛的&#xff0c;能做什么事情&#xff1f;今天我们继续介绍图生图的实用案例-精美二维码的制作。 对…...

C# File.ReadAllLines()报错

项目中需要读取一个文本文件的内容&#xff0c;调用C#的File.ReadAllLines(path)方法&#xff0c;但是报错&#xff0c;就提示unknown exception&#xff0c;也没其他提示了。 文件是在的&#xff0c;并且&#xff0c;如果把文件拷贝到另外一个路径&#xff0c;再次读取是正常…...

LeetCode 1162. As Far from Land as Possible【多源BFS】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

【算法】二分查找(整数二分和浮点数二分)

二分查找也称折半查找&#xff08;Binary Search&#xff09;&#xff0c;是一种效率较高的查找方法&#xff0c;时间复杂度为O(logN)。 二分查找采用了“分治”策略。使用二分查找时&#xff0c;数组中的元素之间得有单调性&#xff08;升序或者降序&#xff09;。 二分的模…...

git压缩/合并多次commit提交为1次commit提交

git压缩/合并N次commit提交为1次commit提交 假设有最近3次提交&#xff1a; commit_id1 commit_id2 commit_id3目标是把以上3次commit合并成1个commit&#xff0c;注意&#xff0c;最新的commit提交在最上面。 在git bash里面的操作步骤&#xff1a; &#xff08;1&#xff0…...

【3519DV500】AI算法承载硬件平台_2.5T算力+AI ISP图像处理_超感光视频硬件方案开发

Hi3519DV500 内置双核 A55 &#xff0c;提供高效、丰富和灵活的CPU 资源&#xff0c;以满足客户计算和控制需求。 Hi3519DV500集成了高效的神经网络推理引擎&#xff0c;最高2.5Tops NN算力&#xff0c;支持业界主流的神经 网络框架。神经网络支持完整的 API 和工具链&#xf…...

Linux系统基础服务启动的方法

服务&#xff0c;其实就是运行在操作系统后台的一个或者多个应用程序&#xff0c;为计算机系统或用户提供某项特定的服务。Linux系统运行的绝大多数服务都是需要安装才有的&#xff0c;例如FTP服务、httpd服务、MySQL、redis、Zookeeper、rabbitmq、vsftpd等等&#xff0c;那么…...

STM32 FLASH 读写数据

1. 《STM32 中文参考手册》&#xff0c;需要查看芯片数据手册&#xff0c;代码起始地址一般都是0x8000 0000&#xff0c;这是存放整个项目代码的起始地址 2. 编译信息查看代码大小&#xff0c;修改代码后第一次编译后会有这个提示信息 2.1 修改代码后编译&#xff0c;会有提示…...

excel功能区(ribbonx)编程笔记--1 初识功能区

再office2003版本以前,excel是具有菜单栏和工具栏的,再office2007及以后的版本中,界面中没有菜单栏和工具栏,使用功能区替换了菜单和工具栏。 您可能意识到自定义用户界面也变得更加困难,其实设置功能区并不会像您想像的那样困难,因为Microsoft也意识到必须有一种方式供开…...

电脑远程接入软件可以进行文件传输吗?快解析内网穿透

电脑远程接入软件的出现&#xff0c;让我们可以在两台电脑之间进行交互和操作。但是&#xff0c;很多人对于这些软件能否进行文件传输还存在一些疑问。下面的文章将解答这个问题。 1.电脑远程接入软件可以进行文件传输。传统上&#xff0c;我们可能会通过传输线或者移动存储设…...

react-native-webview使用postMessage后H5不能监听问题(iOS和安卓的兼容问题)

/* 监听rn消息 */ const eventListener nativeEvent > {//解析数据actionType、extraconst {actionType, extra} nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document&#xff0c;ios用window window.addEventListener(message, eventLis…...

通过LD_PRELOAD绕过disable_functions

LD_PRELOAD LD_PRELOAD是Linux/Unix系统的一个环境变量&#xff0c;它可以影响程序的运行时的链接&#xff0c;它允许在程序运行前定义优先加载的动态链接库。通过这个环境变量&#xff0c;可以在主程序和其动态链接库的中间加载别的动态链接库&#xff0c;甚至覆盖系统的函数…...

Python批量爬虫下载文件——把Excel中的超链接快速变成网址

本文的背景是&#xff1a;大学关系很好的老师问我能不能把Excel中1000个超链接网址对应的pdf文档下载下来。虽然可以手动一个一个点击下载&#xff0c;但是这样太费人力和时间了。我想起了之前的爬虫经验&#xff0c;给老师分析了一下可行性&#xff0c;就动手实践了。    没…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...