C++的类型转换

文章目录

  • 一. C语言的类型转换
  • 二. C++的四种类型转换
    • 1. static_cast
    • 2. reinterpret_cast
    • 3. const_cast
    • 4. dynamic_cast
  • 三. RTTI
  • 结束语

一. C语言的类型转换

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

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
  2. 显示类型转化:需要用户自己指定
void Test ()
{
     int i = 1;
     // 隐式类型转换
     double d = i;
     
     int* p = &i;
     // 显示的强制类型转换
     int address = (int) p;
}

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

二. C++的四种类型转换

C语言风格的转换格式很简单,但是也有缺点:

  1. 隐式类型转化可能出现精度丢失,截断等问题
  2. 显示类型转换将所有情况混合在一起,代码不够清晰

因此C++提出了自己的类型转换风格,引入了四种命名的强制类型转换操作符
static_castreinterpret_castconst_castdynamic_cast

1. static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,即可用于意义相近的类型转换

void test1()
{
	double a = 12.34;
	//都是表述数值
	int b = static_cast<int>(a);
	cout << b << endl;
}

2. reinterpret_cast

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

void test2()
{
	double a = 12.34;
	//都是表述数值
	int b = static_cast<int>(a);
	//数值转换成地址
	int*p = reinterpret_cast<int*>(b);
}

3. const_cast

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

void test3()
{
	const int a = 2;
	//删除const属性
	int *p = const_cast<int*>(&a);
	*p = 3;
	cout << *p << endl;
}

在这里插入图片描述

4. dynamic_cast

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

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

注意:

  1. dynamic_cast 只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否转换成功,能成功则转换,不能则返回0

为什么说向下转型用dynamic_cast是安全的,强制转换为什么不安全?

比如这样一个继承体系

class A
{
public:
	virtual void fun()
	{}
private:
	int _x;
};

class B :public A
{
private:
	int _y;
	int _z;
};

B继承A,但B拥有自己的成员变量,如果强制类型转换,情况如下:

在这里插入图片描述

因为B比A大,所以B的指针能访问的空间更多,但是这部分并不属于A。如果原先是指向A类型对象的指针,那么强转成B类型的指针,访问权限变大,但那部分并不属于A类型对象,这就会造成越界

强制类型转换并不会管原先指向的到底是父类对象还是子类对象,都会转换成功。
而dynamic_cast会检查,如果是原先是父类对象,则转换失败返回0,如果是子类对象,则转换成功。

void fun(A* pa,const string&str)
{
	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回
	cout << str << "转换" << endl;
	B* pb1 = (B*)(pa);
	B* pb2 = dynamic_cast<B*>(pa);
	cout << "pb1:" << pb1 << endl;
	cout << "pb2:" << pb2 << endl << endl;
}

void test4()
{
	A a;
	B b;
	fun(&a,"父类对象");
	fun(&b,"子类对象");
}

在这里插入图片描述

可以看到,强制转换不管父类还是子类对象都会发生转换,而dynamic_cast只有原先指向子类时才会发生转换

注意:
强制类型转换关闭或者挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方式达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。
强烈建议:避免使用强制类型转换

三. RTTI

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

有以下三种方式:

  1. typeid:通过name()函数获取类型名称的字符串
    在这里插入图片描述

  2. dynamic_cast:可以识别一个指针/引用,指向的是父类对象还是子类对象

  3. decltype:自动类型推导
    和auto类似,但是decltype是通过其他对象获取类型

auto x=1;//auto通过=号右边推导
decltype(x) y=1;//decltype通过x推导

auto要求变量必须初始化,因为auto根据变量的初始值来推导变量类型,如果不初始化,变量的类型就无法推导。
而decltype不需要初始化,所以decltype可以适用于只要自动推导类型的场景

比如如下场景:

function<int> add=[](int a,int b)->int{ return a+b; };
set<int,decltype(add)> s;

结束语

感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

25 MFC 数据库

文章目录 导入ADO库 导入ADO库 #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","rsEOF")void CADODlg::OnBnClickedBtnQuery() {//导入ADO库::CoInitialize(NULL);//初始化COM库_ConnectionPtr pCo…

ChatGPT 最佳实践指南

GPT Best Practices GPT 最佳实践指南 This guide shares strategies and tactics for getting better results from GPTs. The methods described here can sometimes be deployed in combination for greater effect. We encourage experimentation to find the methods that…

Python爬虫-贝壳二手房

前言 本文是该专栏的第3篇,后面会持续分享python爬虫案例干货,记得关注。 本文以某二手房网为例,如下图所示,采集对应城市的二手房源数据。具体思路和方法跟着笔者直接往下看正文详细内容。(附带完整代码) 正文 地址:aHR0cHM6Ly9zei5rZS5jb20vZXJzaG91ZmFuZy8= 目标:…

QT调用torch的环境配置(2023.7.19 / Win10+Qt+libtorch(1.9.1)+cuda11.1+cuDNN v8.0.4)

QT/C成功调用libtorch的环境配置&#xff08;2023.7.19&#xff09; QT/C成功调用libtorch的环境配置Pytorch 模型训练下载训练转化 libtorch模型使用下载C使用Qt使用 最后的话 QT/C成功调用libtorch的环境配置 背景&#xff1a;和同门一起搭的新系统是基于QT的&#xff0c;如…

Monocular 3D Object Detection with Depth from Motion 论文学习

论文链接&#xff1a;Monocular 3D Object Detection with Depth from Motion 1. 解决了什么问题&#xff1f; 从单目输入感知 3D 目标对于自动驾驶非常重要&#xff0c;因为单目 3D 的成本要比多传感器的方案低许多。但单目方法很难取得令人满意的效果&#xff0c;因为单张图…

NAT技术是什么?谈谈它的实现方式、优缺点以及作用

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 前言 随着网络的不断发展&#xff0c;网络的应用也越来越多&#xff0c;有限的IPV4地址就显得不怎么够用&#xff0c;所以出现了NAT技术&…

Rust 数据类型 之 结构体(Struct)

目录 结构体&#xff08;Struct&#xff09; 定义与声明 结构体定义 结构体实例 结构体分类 单元结构体&#xff08;Unit Struct&#xff09; 元组结构体&#xff08;Tuple Struct&#xff09; 具名结构体&#xff08;Named Struct&#xff09; 结构体嵌套 结构体方法…

jenkins war包 centos启动安装指导

文章目录 步骤1&#xff1a;进入官网&#xff0c;下载到Jenkins的war包1.1 放置在指定位置1.2 放置安装包和创建文件放置路径1.3 检查环境1.4 配置启动命令和结束命令 步骤2&#xff1a; 启动后进入到Jenkins页面2.1 安装插件&#xff0c;例如流水线2.2 依然出现安装插件失败的…

疑问:为什么我的手机不能同时放两张电信卡呢?联通移动可以

很多后台的小伙伴私信我&#xff1a;“为什么我的双卡双待手机不能用两张电信卡呢&#xff1f;”其实我一直在认真的去查证这个问题&#xff0c;因为现在普遍网上的大流量手机卡套餐&#xff0c;电信是主力&#xff0c;如果第一张卡是电信&#xff0c;第二张卡不能使用电信了&a…

公网访问的Linux CentOS本地Web站点搭建指南

文章目录 前言1. 本地搭建web站点2. 测试局域网访问3. 公开本地web网站3.1 安装cpolar内网穿透3.2 创建http隧道&#xff0c;指向本地80端口3.3 配置后台服务 4. 配置固定二级子域名5. 测试使用固定二级子域名访问本地web站点 前言 在web项目中,部署的web站点需要被外部访问,则…

ES6基础知识一:说说var、let、const之间的区别

一、var 在ES5中&#xff0c;顶层对象的属性和全局变量是等价的&#xff0c;用var声明的变量既是全局变量&#xff0c;也是顶层变量 注意&#xff1a;顶层对象&#xff0c;在浏览器环境指的是window对象&#xff0c;在 Node 指的是global对象 var a 10; console.log(window.…

uview2.0使用u-calendar 的formatter属性,在formatter方法里无法访问this的bug,解决办法!!!!

uview 版本2.0.36 文档 使用该文档的案例&#xff0c;在 formatter打印this也会是undefined。 自己写了个demo 父给子传值v-bind传一个函数&#xff0c;然后在这个函数里面打印this&#xff0c;this是子组件的实例&#xff0c;但是不知道为什么formatter里会打印undefined。希…

微服务 云原生:搭建 K8S 集群

为节约时间和成本&#xff0c;仅供学习使用&#xff0c;直接在两台虚拟机上模拟 K8S 集群搭建 踩坑之旅 系统环境&#xff1a;CentOS-7-x86_64-Minimal-2009 镜像&#xff0c;为方便起见&#xff0c;直接在 root 账户下操作&#xff0c;现实情况最好不要这样做。 基础准备 关…

IntelliJ IDEA Copyright添加

IDEA代码文件的版权(copyright)信息配置 1. 快速创建Copyright 版权配置文件 1.1 创建copyright文件 依次点击 File > Settings… > Editor > Copyright > 点击 “” 号或 “Add profile”***&#xff0c;弹出创建 Copyright Profile 操作窗口&#xff0c;在***文…

低代码如何帮助企业数字化转型?

在数字化时代背景下&#xff0c;企业都面临着巨大的数字化转型挑战。为了迎接这一挑战&#xff0c;企业软件开发工具和平台都在不断地创新和进化。其中&#xff0c;低代码开发平台应运而生&#xff0c;并成为了众多企业转型的首选方案。企业为什么都选择低代码开发平台&#xf…

【基于CentOS 7 的NFS服务】

目录 一、概述 二、应用场景 三、安装 四、启动服务 五、目录结构 1.nfs的主配置文件 2.存储配置文件 六、命令解析 1.共享存储管理命令 2.共享目录查看 七、配置 八、客户端访问 1.查看nfs服务器的共享目录 2.挂载 九、实际案例 一、概述 network filesystemt…

【GitOps系列】使用Kustomize和Helm定义应用配置

文章目录 使用 Kustomize 定义应用改造示例应用1.创建基准和多环境目录2.环境差异分析3.为 Base 目录创建通用 Manifest4.为开发环境目录创建差异 Manifest5.为预发布环境创建差异 Manifest6.为生产环境创建差异 Manifest 部署 Kustomize 应用部署到开发环境部署到生产环境 使用…

Flink笔记

Flink笔记 2.Flink学习笔记2.1流式处理对比2.2 Flink核心概念2.2.1并行度2.2.2算子链2.2.3任务槽 2.3 DataStream2.3.2 读取数据源-源算子&#xff08;Source&#xff09;2.3.3 转换算子&#xff08;Transformation&#xff09; 2.Flink学习笔记 2.1流式处理对比 学习Spark S…

ubuntu22.04上如何创建有privilege权限,有固定自定义IP的空容器

需求背景&#xff1a; 我想用docker来隔离自己的主机环境&#xff0c;来创建一个隔离的空白全新的开发环境&#xff0c;并且使之有固定的IP&#xff0c;在里面可以自由更新下载各种编译依赖&#xff0c;具有privileged权限的容器&#xff0c;以下是操作实现的具体步骤 查看do…

1.12 springboot 整合log4j打印日志

1.除去springboot自带的日志 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><!-- 除去springboot自带的日志 --><exclusion><groupId>org.sprin…