《C++类型转换:四种类型转换的规定》

news2024/11/8 18:43:40

C++类型转换:四种类型转换的规定

  • 1. 内置类型中的类型转换
  • 2. 内置类型和自定义类型的转换
  • 3. 自定义类型转换成内置类型
  • 4. 自定义类型之间的转换
  • 5. C++强制类型转换
    • 5.1 static_cast
    • 5.2 reinterpret_cast
    • 5.3 const_cast
    • 5.4 dynamic_cast
  • 6. RTTI(了解)

🌏个人博客主页:个人主页

在这里插入图片描述
在这里插入图片描述

1. 内置类型中的类型转换

在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);
}

2. 内置类型和自定义类型的转换

class A
{
public:
	explicit A(int a)
		:_a1(a)
		,_a2(a)
	{}

	A(int a1,int a2)
		:_a1(a1)
		,_a2(a2)
	{}
private:
	int _a1 = 1;
	int _a2 = 1;
};

int main()
{
	string s = "11111";
	//单参数的构造函数支持隐式类型转换
	//如果加了explicit不支持隐式类型转换必须强制类型转换
	A aa1 = (A)1;
	//多参数的隐式类型转换
	A aa2 = { 1,2 };

	return 0;
}

3. 自定义类型转换成内置类型

想要实现自定义类型转换成内置类型,需要我们提供对应的运算符重载。

class A
{
public:
	explicit A(int a)
		:_a1(a)
		,_a2(a)
	{}

	A(int a1,int a2)
		:_a1(a1)
		,_a2(a2)
	{}

	//()被仿函数占用了,不能用了
	//operator + 类型,无返回类型
	operator int()
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};

int main()
{
	string s = "11111";
	//单参数的构造函数支持隐式类型转换
	//如果加了explicit不支持隐式类型转换必须强制类型转换
	A aa1 = (A)1;
	//多参数的隐式类型转换
	A aa2 = { 1,2 };
	//临时对象具有常性,需要加const
	const A& aa3 = { 1,2 };

	int x = aa1;
	int y = aa2;

	//本质上转换成函数的调用
	int z = aa2.operator int();

	cout << x << endl; //2
	cout << y << endl; //3

	return 0;
}

在这里插入图片描述

shared_ptr这里就提供了转换成bool类型的运算符重载。
在这里插入图片描述
可以判断这个指针是不是空指针。

在这里插入图片描述

4. 自定义类型之间的转换

自定义类型的相互转换,需要提供对应的构造函数才能相互转换。

class A
{
public:
	explicit A(int a)
		:_a1(a)
		,_a2(a)
	{}

	A(int a1,int a2)
		:_a1(a1)
		,_a2(a2)
	{}

	//()被仿函数占用了,不能用了
	//operator + 类型,无返回类型
	operator int()
	{
		return _a1 + _a2;
	}

	int get() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};

class B
{
public:
	B(int b)
		:_b(b)
	{}
	
	//支持A -> B
	B(const A& aa)
		:_b(aa.get())
	{}
private:
	int _b;
};

int main()
{
	A aa1(1);
	B bb1(2);

	bb1 = aa1;

	//B& ref = aa1;
	const B& ref = aa1;
}

5. C++强制类型转换

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

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

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

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

5.1 static_cast

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

int main()
{
	//对应隐式类型转换 -- 数据的意义没有改变
	double d = 13.14;
	int b = static_cast<int>(d);
	
	return 0;
}

5.2 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;
}

5.3 const_cast

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

int main()
{
	//对应强制类型转换中有风险的去掉const属性
	const int b = 2;
	//int* p2 = (int*)&b;
	int* p2 = const_cast<int*>(&b);
	*p2 = 3;

	cout << b << endl;
	cout << *p2 << endl;
}

在这里插入图片描述
这里可以看到打印的值依然是2,因为编译器优化的原因所以会把const 变量直接替换或者放到寄存器里面在直接从里面读取。

如果不想让编译器将const变量优化到寄存器当中,可以用volatile关键字对const变量进行修饰,这时当要读取这个const变量时编译器就会从内存中进行读取

在这里插入图片描述

5.4 dynamic_cast

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

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

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

向下转换:

如果父类的指针(或引用)指向的是一个父类对象,那么将其转换为子类的指针(或引用)是不安全的,因为转换后可能会访问到子类的资源,而这个资源是父类对象所没有的。

如果父类的指针(或引用)指向的是一个子类对象,那么将其转换为子类的指针(或引用)则是安全的

注意:子类的对象赋值给父类是可以的,但是父类的对象赋值给子类会报错,就算强制类型转换也不可以。
在这里插入图片描述

class A
{
public:
	virtual void f() 
	{}

	int _a = 1;
};
class B : public A
{
public:
	int _b = 2;
};
void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功(指向子类对象),能成功则转换,
	// 指向父类对象不能则返回nullptr
	//B* pb1 = (B*)(pa);
	B* pb1 = dynamic_cast<B*>(pa);
	if (pb1 != nullptr)
	{
		cout << "pb1:" << pb1->_a << endl;
		cout << "pb1:" << pb1->_b << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}
int main()
{
	A a;
	B b;
	fun(&a);
	fun(&b);
	return 0;
}

注意:

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

6. RTTI(了解)

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

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

  1. typeid运算符
  2. dynamic_cast运算符
  3. decltype
    在这里插入图片描述

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

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

相关文章

安全工程师入侵加密货币交易所获罪

一名高级安全工程师被判犯有对去中心化加密货币交易所的多次攻击罪&#xff0c;在此过程中窃取了超过 1200 万美元的加密货币。 沙克布艾哈迈德&#xff08;Shakeeb Ahmed&#xff09;被判刑&#xff0c;美国检察官达米安威廉姆斯&#xff08;Damian Williams&#xff09;称其…

鸿蒙生态崛起:开发者的机遇与挑战

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题 点这里。 实战项目访问&#xff1a;http://javapub.net.cn/ 引言 作为一名技术博主&#xff0c;我对技术趋势始终保持着敏锐的洞察力。在数字化时代&#xff0c;操作系统作为智能设备的核心&#xff0c;其重要性不言而喻。随…

夜天之书 #103 开源嘉年华纪实

上周在北京参与了开源社主办的 2024 中国开源年会。其实相比于有点明显班味的“年会”&#xff0c;我的参会体验更像是经历了一场中国开源的年度嘉年华。这也是在会场和其他参会朋友交流时共同的体验&#xff1a;在开源社的 COSCon 活动上&#xff0c;能够最大限度地一次性见到…

【Linux】信号三部曲——产生、保存、处理

信号 1. 信号的概念2. 进程如何看待信号3. 信号的产生3.1. kill命令3.2. 终端按键3.2.1. 核心转储core dump3.2.2. OS如何知道键盘在输入数据 3.3. 系统调用3.3.1. kill3.3.2. raise3.3.3. abort 3.4. 软件条件3.4.1. SIGPIPE信号3.4.2. SIGALRM信号 3.5. 硬件异常3.5.1. 除零异…

昔日IT圈的热点话题“虚拟化和容器技术路线之争”,现在怎么样了?

“以收单系统为例&#xff0c;虚拟化纯容器在轻量级云平台上融合&#xff0c;实现了对稳态和敏态业务支撑&#xff0c;核心数据库依托于稳定可靠的虚拟机环境&#xff0c;应用趋于敏态创新型应用类业务则采用容器技术部署&#xff0c;实现动态扩展&#xff0c;弹性伸缩&#xf…

智能网联汽车:人工智能与汽车行业的深度融合

内容概要 在这个快速发展的时代&#xff0c;智能网联汽车已经不再是科幻电影的专利&#xff0c;它正在悄然走进我们的日常生活。如今&#xff0c;人工智能&#xff08;AI&#xff09;技术与汽车行业的结合犹如一场科技盛宴&#xff0c;让我们看到了未来出行的新方向。通过自动…

【北京迅为】《STM32MP157开发板嵌入式开发指南》-第七十一章 制作Ubuntu文件系统

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

ZABBIX API获取监控服务器OS层信息

Zabbix 是一款强大的开源监控解决方案,能够通过其 API 接口自动化管理和获取监控数据。在这篇文章中,详细讲解如何通过 Zabbix API 批量获取服务器的系统名称、IP 地址及操作系统版本信息,并将数据保存到 CSV 文件中。本文适合对 Python 编程和 Zabbix 监控系统有一定基础的…

【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!

数据集列表 帮忙采集开源数据集&#xff0c;包括YOLO格式数据集和Pascal VOC格式数据集&#xff0c;含图像原文件和标注文件&#xff0c;几百张到几千张不等&#xff0c;国内外公开数据集均可。 针对目标检测&#xff0c;YOLO系列模型训练&#xff0c;分类训练等。 部分数据…

万字长文详解:SpringBoot-Mybatis源码剖析

目录 背景 传统的Mybaits开发方式&#xff0c;是通过mybatis-config.xml对框架进行全局配置&#xff0c;比如&#xff1a;一级缓存、主键生成器等。 而在SpringBoot发布后&#xff0c;通过引入 mybatis-spring-boot-starter依赖包&#xff0c;可以大大减少工作量&#xff0c;实…

[IAA系列] Image Aesthetic Assessment

Preface 本文旨在记录个人结合AI工具对IAA这个领域的一些了解&#xff0c;主要是通过论文阅读的方式加深对领域的了解。有什么问题&#xff0c;欢迎在评论区提出并讨论。 什么是IAA Image Aesthetic Assessment&#xff08;图像美学评估&#xff09;是一种评估图像在视觉上的…

leetcode 2043.简易银行系统

1.题目要求: 示例: 输入&#xff1a; ["Bank", "withdraw", "transfer", "deposit", "transfer", "withdraw"] [[[10, 100, 20, 50, 30]], [3, 10], [5, 1, 20], [5, 20], [3, 4, 15], [10, 50]] 输出&#xff…

一文了解Android SELinux

在Android系统中&#xff0c;SELinux&#xff08;Security-Enhanced Linux&#xff09;是一个增强的安全机制&#xff0c;用于对系统进行强制访问控制&#xff08;Mandatory Access Control&#xff0c;MAC&#xff09;。它限制了应用程序和进程的访问权限&#xff0c;提供了更…

Java链表及源码解析

文章目录 创建一个ILindkedList接口创建方法(模拟实现链表方法)创建MyLinkedList来实现接口的方法创建链表节点addFirst方法&#xff08;新增头部属性&#xff09;addLast方法&#xff08;新增到末尾一个属性&#xff09;remove方法&#xff08;删除指定属性&#xff09;addInd…

微服务系列四:热更新措施与配置共享

目录 前言 一、基于Nacos的管理中心整体方案 二、配置共享动态维护 2.1 分析哪些配置可拆&#xff0c;需要动态提供哪些参数 2.2 在nacos 分别创建共享配置 创建jdbc相关配置文件 创建日志相关配置文件 创建接口文档配置文件 2.3 拉取本地合并配置文件 2.3.1 拉取出现…

NoETL自动化指标平台为数据分析提质增效,驱动业务决策

直觉判断往往来源于多年的经验和专业知识&#xff0c;能够在复杂和不确定的环境中快速做出决策反应。但这种方式普遍存在主观偏见&#xff0c;缺乏合理的科学依据&#xff0c;无法全面、客观、精准地评估和识别市场趋势与用户需求&#xff0c;从而造成决策失误&#xff0c;给业…

使用亚马逊 S3 连接器为 PyTorch 和 MinIO 创建地图式数据集

在深入研究 Amazon 的 PyTorch S3 连接器之前&#xff0c;有必要介绍一下它要解决的问题。许多 AI 模型需要使用无法放入内存的数据进行训练。此外&#xff0c;许多为计算机视觉和生成式 AI 构建的真正有趣的模型使用的数据甚至无法容纳在单个服务器附带的磁盘驱动器上。解决存…

基于MATLAB的实现垃圾分类Matlab源码

⼀、垃圾分类 如何通过垃圾分类管理&#xff0c;最⼤限度地实现垃圾资源利⽤&#xff0c;减少垃圾处置量&#xff0c;改善⽣存环境质量&#xff0c;是当前世界各国共同关注的迫切问题之⼀。根据国家制定的统⼀标准&#xff0c;现在⽣活垃圾被⼴泛分为四类&#xff0c;分别是可…

硬件基础10 逻辑门电路——CMOS

目录 一、门电路类型 二、CMOS逻辑门 1、CMOS基础 2、MOS管开关电路 &#xff08;1&#xff09;、基础理论分析 &#xff08;2&#xff09;、开关动态特性 3、CMOS反相器 4、与非、或非门 三、逻辑门的不同输出结构与参数 1、CMOS的保护和缓冲 2、漏极开路与三态输出…

新手散户如何避免被割?有量化策略适应暴涨暴跌行情吗?|附代码

这是邢不行第 124 期量化小讲堂的分享 作者 | 邢不行 大A今年上半年的行情较为坎坷&#xff0c;市场持续下跌&#xff0c;导致诸多投资者风格大变&#xff0c;从倾向于高风险的进攻策略转为低风险的防御策略&#xff0c;尤以高股息策略和杠铃策略最为火爆。 本文给大家介绍一…