C/C++类型转换

目录

C语言中的类型转换

隐式类型转换:

 显示类型转换:

 总结:

C++中的类型转换

static_cast:

reinterpret_cast:

const_cast:

dynamic_cast:

RTTI

C语言中的类型转换

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

隐式类型转换:

编译器在编译阶段自动进行,能转就转,不能转就编译失败。

主要包括:整型家族之间的类型转换整型和浮点型之间bool和整型之间、bool和浮点型之间指针->bool

C++中又引入了内置类型类类型之间(构造函数和操作符重载的支持)和类类型之间的转换

class A
{
public:
	//单参数构造函数,支持隐式类型转换
	A(int a)
		:_a(a)
	{}
private:
	int _a;
};

class B
{
public:
	//全缺省构造函数,支持隐式类型转换
	B(int x = 1,int y = 2)
		:_x(x),_y(y)
	{}
    
    operator int()
	{
		return _x + _y;
	}
private:
	int _x;
	int _y;
};


int main()
{
	char temp = 'a';
	int a = temp;//整型家族之间隐式类型转换

	double b = a;//整型和浮点数之间隐式类型转换

	bool c = a;//bool和整型

	double d = c;//bool和浮点型

	int* p = &a;
	c = p;//指针->bool合法的隐式转换
	//p = c;//bool->指针非法的隐式转换

	A a1 = a;//内置类型->类类型

	B b1 = 20;
    int sum1 = b1;//类类型->内置类型
    int sum2 = (int)b1;

	initializer_list<int> il{ 1,2,3,4,5 };
	vector<int> v{ il };//类类型之间

	return 0;
}

 指针->bool

  • 非空指针​(指向合法内存的指针)会被隐式转换为true
  • 空指针​(NULL)会被隐式转换为false

bool->指针

  • 布尔值(true/false)仅为10,若隐式转为指针,true会被视为非零地址(如0x1),false可能被解释为NULL,但这与bool的原始意图无关,属于未定义行为。
  • 虽然可以通过强制类型转换将bool转为指针(如(int*)true),但这完全依赖编译器和系统实现,属于未定义行为,是极其危险的行为。

C++内置类型->类类型

  • 单参数构造函数或者多参数但只需要传入一个参数的构造函数,支持将内置类型隐式转换为自定义类型,在类与对象一文中有详细讲解。
  • 若要禁止这种隐式转换,需要使用explicit关键字修饰构造函数。

C++类类型->内置类型

  • 需要在类内进行相关的运算符重载(如operator int()),当类对象转换为对应类型时,会自动调用。

C++类类型之间的转换

  • 同样是构造函数支持的。

缺点

由于是编译器自动进行的转换,可能会出现意外截断或提升的问题。

 显示类型转换:

需要用户通过强制类型转换手动指定转换类型。

主要包括:指针类型整型之间、不同类型的指针之间。

int main()
{
	int a = 10;
	int* p1 = (int*)a;//整型->指针
	int b = (int)p1;//整型->指针

	double* p2 = (double*)p1;//int*->double*

	return 0;
}

 缺点

需要用户手动确保安全性,对用户要求较高。

 总结:

  • 尽量避免不必要的类型转换,尤其是隐式转换。

  • 使用显式转换时,确保转换后的值在目标类型的有效范围内。

  • 对指针和函数指针的转换需格外谨慎。

C++中的类型转换

C语言的类型转换格式很简单,但是有不少缺点的:
1. 隐式类型转换有些情况下可能会出问题:比如数据精度丢失
2. 显式类型转换将所有情况混合在一起,代码不够清晰
因此C++提出了自己的类型转化风格,但是因为C++要兼容C语言,所以C++中还可以使用C语言的转换风格的。

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

static_cast:

编译时检查,用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用,属于隐式类型转换,但是相较于普通的隐式类型转换,static_cast是可视明确告知了存在类型转换,以及要转换的类型,提高了代码的安全性和可读性

需要注意的是static_cast不能用于不相关的类型之间进行转换

int main()
{
	char temp = 'a';
	double d = 1.23;
	int a = static_cast<int>(d);//double->int
	a = static_cast<int>(temp);//char->int

	//int* p = static_cast<int*>(&d);//错误的,int*和double*是不相关的两个类型

	return 0;
}

reinterpret_cast:

reinterpret_cast是最底层的类型转换运算符,用于执行二进制级别的重新解释。它不进行任何编译时类型安全检查,几乎可以强制转换任何指针或整数类型到其他类型,但使用时需高度谨慎,因为可能导致未定义行为。属于强制类型转换

int main()
{
	double d = 1.23;
	int* p = reinterpret_cast<int*>(&d);//double*->int*
	int b = reinterpret_cast<int>(p);//int*->int

	return 0;
}

const_cast:

const_cast是专门用于添加或移除const和volatile限定符的类型转换运算符。它允许开发者显式绕过类型系统的常量性检查,但需谨慎使用,否则可能导致未定义行为。

int main()
{
	const int a = 10;
	cout << "a:" << a << endl;

	int* p = const_cast<int*>(&a);
	*p = 3;
	cout << "*p:" << *p << endl;
	cout << "a:" << a << endl;

	return 0;
}

上边的代码通过const_cast<int*>将const int*类型的&a转换为int*类型,并赋值给p,再通过指针p修该a的值,编译运行:

可以发现a的值并没有改变,是因为const_cast操作符没有作用吗?但是否定的,a的值之所以没有改变是因为编译器会把const常量的值存放在寄存器中每次读取时直接去寄存器中读取数据,而通过指针p修改的是a在内存中的数据,但是并不会影响寄存器中的数据,因此再次输出a的值时会显示没有改变。要想保持寄存器和内存中数据的一致性,可以通过volatile修饰变量实现。

int main()
{
	//const int a = 10;
	volatile const int a = 10;
	cout << "a:" << a << endl;

	int* p = const_cast<int*>(&a);
	*p = 3;
	cout << "*p:" << *p << endl;
	cout << "a:" << a << endl;

	return 0;
}

dynamic_cast:

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(dynamic_cast会进行类型检查,保证安全性,常规的强转或者使用reinterpret_cast/static_cast也可以实现,但是它们不会进行类型检查,存在风险)

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

class A
{
public:
	virtual void f() {}
};
class B : public A
{};
void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回
	B* pb1 = static_cast<B*>(pa);
	B* pb2 = reinterpret_cast<B*>(pa);
	B* pb3 = dynamic_cast<B*>(pa);
	cout << "pb1:" << pb1 << endl;
	cout << "pb2:" << pb2 << endl;
	cout << "pb3:" << pb3 << endl;
}
int main()
{
	A a;
	B b;
	fun(&a);
	fun(&b);
	return 0;
}

上述代码定义了一个含有虚函数的基类A,通过A派生出B类,通过fun函数,分别传入A*参数和B*参数,在fun函数中对参数进行类型转换,观察结果:

可以发现dynamic_cast的类型转换是更加安全的,当想要将一个实际指向父类的指针转换为子类指针时,dynamic_cast无法完成转换,保证了安全性。

RTTI

RTTI(Runtime Type Information)即运行时类型识别,是C++中用于在程序运行时获取对象类型信息的机制,主要支持dynamic_cast和typeid操作。

typeid:返回一个type_info对象的指针,描述表达式在运行时的类型。

dynamic_cast:在多态场景下,将基类指针/引用安全地转换为派生类类型,需运行时检查类型是否合法。

除了运行时获取类型信息,还有编译时获取类型信息:

decltype:是在编译时获取类型信息。

int main()
{
	int a = 10;
	decltype(a) b;
	cout << typeid(b).name() << endl;

	return 0;
}

上述代码中decltype获取a的类型后,又定义了b,通过typeid输出b的类型。

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

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

相关文章

发行基础:宣传片

转载自官方文件 --------------- 宣传片 概览 作为 Steam 发行流程的一部分&#xff0c;您需要上传自己产品的宣传片。 宣传片将会显示在您的产品商店页的顶端&#xff0c;通常是您的潜在客户第一眼会看见的内容。 最佳实践 在 Steam 平台上&#xff0c;宣传片是产品营销中…

MyBatis-Plus (超详细 Spring版)

1 MyBatis-Plus 简介 1.1 简介 MyBatis-Plus&#xff08;简称MP&#xff09;是一个 MyBatis的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为 简化开发、提高效率而生。 1.2 特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有…

地下井室可燃气体监测装置:守护地下安全,防患于未“燃”!

在城市的地下&#xff0c;隐藏着无数的燃气管道和井室&#xff0c;它们是城市基础设施建设的重要部分&#xff0c;燃气的使用&#xff0c;给大家的生活提供了极大的便利。在便利生活的背后&#xff0c;也存在潜在的城市安全隐患。 近年来&#xff0c;地下井室可燃气体泄漏事故…

BGP 基本配置实验

实验拓扑 实验需求 按照图示配置 IP 地址&#xff0c;R1 和 R5 上使用环回口模拟业务网段&#xff0c;R2&#xff0c;R3&#xff0c;R4 的环回口用于配置 Router-id 和建立 IBGP 邻居AS 200 运行 OSPF 实现内部网络互通R1&#xff0c;R2&#xff0c;R4&#xff0c;R5 运行 BGP…

解锁AIGC新时代:通义万相2.1与蓝耘智算平台的完美结合引领AI内容生成革命

前言 通义万相2.1作为一个开源的视频生成AI模型&#xff0c;在发布当天便荣登了VBench排行榜的榜首&#xff0c;超越了Sora和Runway等业内巨头&#xff0c;展现出惊人的潜力。模型不仅能够生成1080P分辨率的视频&#xff0c;而且没有时长限制&#xff0c;能够模拟自然动作&…

梦三国2游戏下载

梦三国2是由杭州电魂网络科技股份有限公司自主研发的一款将rts元素融合到rpg网游中的即时战略网络游戏。该作保留了前作的三国文化背景&#xff0c;继承了其特色玩法&#xff0c;优化了画面和操作体验&#xff0c;还基于玩家们的需求提供了有趣新颖的地图和系统。游戏主要分为p…

模型微调-基于LLaMA-Factory进行微调的一个简单案例

模型微调-基于LLaMA-Factory进行微调的一个简单案例 1. 租用云计算资源2. 拉取 LLaMa-Factory3. 安装依赖环境4. 启动 LLaMa-Factory 界面5. 从 Huggingface 下载模型6. 模型验证7. 模型微调 1. 租用云计算资源 以下示例基于 AutoDL 云计算资源。 在云计算平台选择可用的云计…

【十三】Golang 通道

&#x1f4a2;欢迎来到张胤尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 通道通道声明初始化缓冲机制无缓冲通道代码示例 带…

聊天服务器分布式改造

目前的聊天室是单节点的&#xff0c;无论是http接口还是socket接口都在同一个进程&#xff0c;无法承受太多人同时在线&#xff0c;容灾性也非常差。因此&#xff0c;一个成熟的IM产品一定是做成分布式的&#xff0c;根据功能分模块&#xff0c;每个模块也使用多个节点并行部署…

DeepSeek 医疗大模型微调实战讨论版(第一部分)

DeepSeek医疗大模型微调实战指南第一部分 DeepSeek 作为一款具有独特优势的大模型,在医疗领域展现出了巨大的应用潜力。它采用了先进的混合专家架构(MoE),能够根据输入数据的特性选择性激活部分专家,避免了不必要的计算,极大地提高了计算效率和模型精度 。这种架构使得 …

深入解析 BitBake 日志机制:任务调度、日志记录与调试方法

1. 引言&#xff1a;为什么 BitBake 的日志机制至关重要&#xff1f; BitBake 是 Yocto 项目的核心构建工具&#xff0c;用于解析配方、管理任务依赖&#xff0c;并执行编译和打包任务。在 BitBake 构建过程中&#xff0c;日志记录机制不仅用于跟踪任务执行情况&#xff0c;还…

OpenCV计算摄影学(16)调整图像光照效果函数illuminationChange()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 对选定区域内的梯度场应用适当的非线性变换&#xff0c;然后通过泊松求解器重新积分&#xff0c;可以局部修改图像的表观照明。 cv::illuminati…

【DuodooTEKr 】多度科技 以开源之力,驱动企业数字化转型

多度科技 背景 / Background 在全球产业链重构与国内经济双循环的浪潮下&#xff0c;中国制造业与贸易企业正面临数字化升级的迫切需求。开源技术作为数字化转型的基石&#xff0c;不仅能打破技术壁垒、降低企业成本&#xff0c;更能通过协作创新加速产业智能化进程。 多度科技…

VBA经典应用69例应用7:从字符串中删除数字

《VBA经典应用69例》&#xff08;版权10178981&#xff09;&#xff0c;是我推出的第九套教程&#xff0c;教程是专门针对初级、中级学员在学习VBA过程中可能遇到的案例展开&#xff0c;这套教程案例众多&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以便…

Vue 系列之:插槽

前言 插槽是定义在子组件中的&#xff0c;相当于一个占位符&#xff0c;父组件可以在这个占位符中填充HTML代码、组件等内容。 插槽显不显示、怎样显示是由父组件来控制的&#xff0c;而插槽在哪里显示就由子组件来进行控制。 基本使用 子组件&#xff1a; <template&g…

一周热点-OpenAI 推出了 GPT-4.5,这可能是其最后一个非推理模型

在人工智能领域,大型语言模型一直是研究的热点。OpenAI 的 GPT 系列模型在自然语言处理方面取得了显著成就。GPT-4.5 是 OpenAI 在这一领域的又一力作,它在多个方面进行了升级和优化。 1 新模型的出现 GPT-4.5 目前作为研究预览版发布。与 OpenAI 最近的 o1 和 o3 模型不同,…

IP,MAC,ARP 笔记

1.什么是IP地址 IP 地址是一串由句点分隔的数字。IP 地址表示为一组四个数字&#xff0c;比如 192.158.1.38 就是一个例子。该组合中的每个数字都可以在 0 到 255 的范围内。因此&#xff0c;完整的 IP 寻址范围从 0.0.0.0 到 255.255.255.255。 IP 地址不是随机的。它们由互…

【A2DP】MPEG - 2/4 AAC 编解码器互操作性要求详解

目录 一、概述 二、编解码器特定信息元素(Codec Specific Information Elements ) 2.1 信息元素结构 2.2 对象类型(Object Type) 2.3 MPEG - D DRC 2.4 采样频率(Sampling Frequency) 2.5 通道(Channels) 2.6 比特率(Bit rate) 2.7 可变比特率(VBR) 三、…

网络安全规划重安全性需求

1.网络安全基本内容 安全包括哪些方面 操作系统内部的安全包括&#xff1a;数据存储安全、应用程序安全、操作系统安全。 此外还有网络安全、物理安全、用户安全教育。 网络安全&#xff1a; 网络安全是指网络系统的硬件、软件及其系统中的数 据受到保护&#xff0c;不因偶然…

发展史 | 深度学习 / 云计算

注&#xff1a;本文为来自 csdn 不错的“深度学习 / 云计算发展史 ” 相关文章合辑。 对原文&#xff0c;略作重排。 深度学习发展史&#xff08;1943-2024 编年体&#xff09;&#xff08;The History of Deep Learning&#xff09; Hefin_H 已于 2024-05-23 15:54:45 修改 …