C++的类型转换

前言

        我们都知道C++是兼容C语言的在C语言中存在两种方式的类型转换,分别是隐式类型转换和显示类型转换(强制类型转换),但是C++觉得C语言的这套东西是够好,所以在兼容C语言的基础上又搞了一套自己的关于类型转换的东西。

目录

1.C语言中的类型转换

2.C++中的类型转换

        3.1static_cast

        3.2reintrepret_cast

        3.3const_cast

        3.4dynamic_cast 

3.RTTI


1.C语言中的类型转换

        在C语言中如果赋值运算符的左右两侧值的类型不同,或者形参与实参的类型不匹配,或者返回值类型与接受返回值类型不匹配,就会发生类型转换, C语言中存在两种方式的类型转换,分别是隐式类型转换和显示类型转换(强制类型转换)。

        1.隐式类型转换:编译器在编译的阶段自己进行,能转就转,不能转就会报错,编译失败。一般用于相近的类型

        2.显示类型转换:需要用户自己处理。

         

void Test1()
{int a = 10;double b = 2.2;//隐式类型转换a = b;cout << a;//显示类型转换--强制类型转换int* p = (int*)a;cout << p << endl;
}

        缺点:比较暴力,可视性不够好,所有的转换都是以一种形式书写的,难以跟踪错误的转换。 

2.C++中的类型转换

         所以C++在兼容C语言的基础之上搞出来了自己的一套东西,来对C语言做的不好的地方进行优化,但是这里只是建议使用C++自己的类型转换方式,还是兼容C语言的方式的。

        标准的C++引入了四种命名的强制类型转换符:

        static_cast,reinterpret_cast,const_cast,dynamic_cast.

        3.1static_cast

        statci_cast用于非多态的类型转换,和C语言中的隐式类型转换一样。不能用于两个不相关的类型之间的转换。

void Test2()
{int a = 10;double b = 2.3;a = static_cast<int>(b);//和C语言中的隐式类型转换一致cout << a;
}

 

        3.2reintrepret_cast

        reinterpret_cast用于两个不想关的类型之间的强制类型转换,与C语言中的强制类型转换大部分是一致的。(除了const类型等的转换)

void Test3()
{int a = 9;double* p = nullptr;p = reinterpret_cast<double*>(a);cout << p << endl;
}

 

        3.3const_cast

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

void Test4()
{const int c = 90;int* p = const_cast<int*>(&c);cout << *p << endl;
}

         这里有一个有意思的问题,我们可以一起来看看。

        如果将*p的值改了,c的值会变吗?

void Test4()
{const int c = 90;int* p = const_cast<int*>(&c);cout << *p << endl;//如果将*p改为10,c的值会变吗?(*p) = 20;cout <<"*p = " << *p << endl;cout<<"c = " << c << endl;
}

        结果是不会改变的,为什么呢?

 

        因为在变量c是const修饰的,所以理论上是不会改变的,所以编译器会对变量c进行处理,将变量c的值存储在寄存器中,虽然*p = 20,确实改变了 变量c的值,但是程序在执行的时候并没有去内存中拿C的值,而是去寄存器中拿c的值所以就会看到这样的结果,实际上是编译器的优化导致的。

        怎么解决这个问题呢?需要对变量加关键字volatile。

void Test4()
{// const int c = 90;volatile const int c = 90;int* p = const_cast<int*>(&c);cout << "c = " << c << endl;//如果将*p改为10,c的值会变吗?(*p) = 20;cout <<"*p = " << *p << endl;cout<<"c = " << c << endl;
}

        加上volatile后,程序会去内存中取这个变量的值。 

        3.4dynamic_cast 

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

        向上转型:子类对象的指针/引用给父类对象的指针/引用的过程(不需要转换,赋值兼容规则),也就是我们常说的切片

        向下转型:父类对象的指针/引用给子类对象的指针/引用的过程(用dynamic_cast进行类型转换是安全的) 。

        注意:

        1.dynamic_cast只能用于父类是多态类的情况,也就是父类必须有虚函数。

        2.dynamic_cast会先检查转换是否成功如果成功则转换,失败则返回0

        

class A
{
public:virtual void func(){}int _a = 10;
};
class B :public A
{
public:int _b = 20;
};
void Fun(A& a)
{B *b = (B*)&a;cout << b->_a << endl << b->_b << endl;
}
int main()
{A a1;B b1;Fun(a1);//如果没有采用dynamic_cast进行动态类型转化这里就会报错,cout打印的是随机值,因为这块空间是不允许被访问的//Fun(b1);return 0;
}

         如果没有采用dynamic_cast进行动态类型转化这里就会报错,cout打印的是随机值,因为这块空间是不允许被访问的。

class A
{
public:virtual void func(){}int _a = 10;
};
class B :public A
{
public:int _b = 20;
};
void FunDynamic(A& a)
{B* pb = dynamic_cast<B*>(&a);if (pb)//通过返回值进行判断{cout << pb->_a << endl << pb->_b << endl;}else{cout << "类型转换失败!" << endl;}
}
int main()
{A a1;B b1;FunDynamic(a1);FunDynamic(b1);return 0;
}

        dynamic_cast的原理:

        为什么dynamic只能用于父类是多态类的情况呢?这就和dynamic的实现原理有关系了,在虚表上方中有一个位置是专门表示类的类别的,dynamic_cast就是专门去这块空间中取数据判断类的类别,从而区分到底是父类对象还是子类对象,如果是父类对象就会返回0。 这就是为什么要是父类是多态类的原因。

         

3.RTTI

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

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

        1.typeid运算符

        2.dynamic_cast

        3.decltype

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

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

相关文章

2023高教社杯数学建模C题思路代码 - 蔬菜类商品的自动定价与补货决策

# 1 赛题 在生鲜商超中&#xff0c;一般蔬菜类商品的保鲜期都比较短&#xff0c;且品相随销售时间的增加而变差&#xff0c; 大部分品种如当日未售出&#xff0c;隔日就无法再售。因此&#xff0c; 商超通常会根据各商品的历史销售和需 求情况每天进行补货。 由于商超销售的蔬菜…

mysql创建用户

创建用户 创建 -- 创建用户 itcast , localhost只能够在当前主机localhost访问, 密码123456; create user test01localhost identified by 123456;使用命令show databases;命令&#xff0c;只显示一个数据库&#xff0c;因为没有权限 -- 创建用户 test02, 可以在任意主机访问…

Stream API

Stream API执行流程 Stream API(java.util.stream)把真正的函数式编程风格引入到Java中,可以极大地提高程序员生产力&#xff0c;让程序员写出高效、简洁的代码 实际开发中项目中多数数据源都是来自MySQL、Oracle等关系型数据库,还有部分来自MongDB、Redis等非关系型数据库 …

vue3路由跳转params传参接收不到

import { useRouter } from "vue-router";const router useRouter(); // 提现记录 const withdrawalClick (item) > {router.push({ name: "Devwithdrawal", params: { name: 123 } }); };//跳转页面接收参数 import { useRoute } from "vue-rou…

网络是如何进行通信

网络是如何进行通信的 简介 在现代社会中&#xff0c;网络已经成为我们生活中不可或缺的一部分。从上网搜索信息、在线购物到远程工作和社交媒体&#xff0c;我们几乎无时无刻不与网络保持着联系。但是&#xff0c;网络究竟是个什么玩意&#xff0c;它是如何工作的呢&#xf…

Web服务器简介及HTTP协议

一、Web Server&#xff08;网页服务器&#xff09; 一个 Web Server 就是一个服务器软件&#xff08;程序&#xff09;&#xff0c;或者是运行这个服务器软件的硬件&#xff08;计算机&#xff09;。其主要功能是通过 HTTP 协议与客户端&#xff08;通常是浏览器&#xff08…

python可视化模块—快速利用matplot绘制图表

文章目录 一、Matplotlib基本介绍二、两种绘图方式区别&#xff08;plt.*** 和ax.***&#xff09;三、如何使用Matplotlib绘图1、画布—绘画的画板2、配置—更个性化的绘图全局配置局部配置面向对象绘图过程&#xff1a;ax代表子图变量过程式绘图过程 四、常用绘图图形如何选择…

配电房能源监测系统

配电房能源监测系统是一种能够实时监测和管理配电房能源消耗的系统&#xff0c;有助于企业更好地管理能源使用&#xff0c;降低能源成本&#xff0c;提高能源利用效率。本文将详细介绍配电房能源监测系统的组成、功能和优点。 一、配电房能源监测系统的组成 配电房能源监测系统…

网络通信深入解析:探索TCP/IP模型

http协议访问web 你知道在我们的网页浏览器的地址当中输入url&#xff0c;未必是如何呈现的吗&#xff1f; web浏览器根据地址栏中指定的url&#xff0c;从web服务器获取文件资源&#xff08;resource&#xff09;等信息&#xff0c;从而显示出web页面。web使用HTTP&#xff08…

OpenHarmony 使用 ArkUI Inspector 分析布局

● 摘要&#xff1a;视图的嵌套层次会影响应用的性能&#xff0c;开发者应该移除多余的嵌套层次&#xff0c;缩短组件刷新耗时。本文会介绍如何使用 ArkUI Inspector 工具分析布局&#xff0c;提示应用响应性能。 ● 关键字&#xff1a;列举本文相关的关键字&#xff1a;OpenH…

vue3:3、项目目录和关键文件

关于vsvode的更改 <!-- 加上setup允许在script中直接编写组合式api --> <script setup> // 组件引入后直接用 import HelloWorld from ./components/HelloWorld.vue import TheWelcome from ./components/TheWelcome.vue</script><!-- 1、js放在最上面&am…

Mavan进阶之多模块(聚合)

文章目录 Maven 多模块&#xff08;聚合&#xff09;非父子关系的多模块项目 Maven 多模块&#xff08;聚合&#xff09; Maven 继承和聚合是 2 个独立的概念。工程与工程之间可能毫无关系&#xff0c;也可能是继承关系&#xff0c;也可能是聚合关系&#xff0c;也可能既是继承…

美客多选品趋势分析,美客多选品时的注意事项

都知道选品的重要性&#xff0c;美客多这个平台也一样&#xff0c;选品选对了肯定事半功倍&#xff0c;本文介绍了美客多选品趋势分析&#xff0c;美客多选品时的注意事项&#xff0c;一起来了解下吧。、 美客多选品趋势分析 1、墨西哥站&#xff1a;跨境支付高&#xff0c;偏…

CSS---flex布局

主要记录flex布局的要点以及实例 flex flex父标签的6个属性flex-direction: flex布局的方向flex-wrap: 是否可以换行flex-flow: flex-direction 和 flex-wrap 一起写justify-content&#xff1a;横向对齐方式align-items: 纵向对齐方式align-content: 有换行情况下的纵向对齐方…

【MySQL系列】MySQL的事务管理的学习(一)_ 事务概念 | 事务操作方式 | 事务隔离级别

「前言」文章内容大致是MySQL事务管理。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、事务概念二、事务的版本支持三、事务提交方式四、事务常见的操作方式4.1 事务正常操作4.2 事务异常验证 五、事务隔离级别5.1 查看与设置隔离性5.2 读未提交&…

jmeter 准确的吞吐量定时器 Precise Throughput Timer

准确的吞吐量定时器使用实例 提取码&#xff1a;gpex&#xff1a; 说明&#xff1a;配置10个线程&#xff0c;每个线程请求200次&#xff0c;通过准确地的定时器模拟QPS为20的场景 配置测试接口参考链接 配置jmeter测试脚本&#xff0c;主要关注准确的吞吐量定时器参数配置 目…

OpenCV(二十六):边缘检测(二)

目录 1.Laplacian算子边缘检测 原理&#xff1a; Laplacian边缘检测函数Laplacian() 示例代码&#xff1a; 2.Canny算子边缘检测 原理&#xff1a; Canny算法函数Canny() 示例代码&#xff1a; 1.Laplacian算子边缘检测 原理&#xff1a; Laplacian算子的原理基于图像…

uniapp分包 解决分多个包的问题

1. 分包可以分很多个, 但是在"optimization": { "subPackages": true } 里面只能写一个, 2. 想分多个包 , 在 pages.json 里面 的 subPackages 里面继续加 第三个 第四个即可 3. 保存之后 创建页面就可以看见多个包了

固定资产台账怎么管理

固定资产台账是指企业对固定资产进行登记、分类、统计和管理的账簿。云呐固定资产管理系统是一款专业的固定资产管理软件&#xff0c;可以帮助企业实现资产全生命周期管理&#xff0c;包括资产采购、入库、领用、归还、维修、报废等环节。系统具有实时监控、预警提醒、报表分析…

java+ssm+mysql水费管理系统

项目介绍&#xff1a; 使用javassmmysql开发的用户水费管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理、用户管理、用水管理&#xff08;用水记录、缴费提醒&#xff09;、水费…