C/C++类型转换

news2024/11/25 9:52:48

目录

  • 一、C语言中的类型转换
  • 二、C++中的类型转换
    • 2.1 C++的四种类型转换
      • 2.1.1 static_cast
      • 2.1.2 reinterpret_cast
      • 2.1.3 const_cast
      • 2.1.4 dynamic_cast
  • 三、RTTI(了解)
  • 四、特殊的类型转换

一、C语言中的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化。
C语言中总共有两种形式的类型转换:
1、隐式类型转换:编译器在编译阶段自动进行,能转就转,不能转就编译失败。
2、显式类型转换:需要用户自己处理。(一般是强制类型转换)

int main()
{
	int a = 1.2;
	double b = a;//发生隐式类型转换

	double* pa = (int*)&a;//强制类型转换

	return 0;
}

缺陷:转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。并且隐式类型转换我们是不清楚的,哪里转换了不能直观地看出来,所以有可能导致程序出现一些奇奇怪怪的问题。

二、C++中的类型转换

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

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

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

2.1 C++的四种类型转换

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:1、static_cast 2、reinterpret_cast
3、const_cast 4、dynamic_cast

2.1.1 static_cast

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

	//相关类型的转换
	double a = 1.2;
	int b = static_cast<int>(a);
	cout << b << endl;

2.1.2 reinterpret_cast

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

	//不相关类型之间的转换
	// 这里写static_cast会报错
	//int pa = static_cast<int>(&a);
	int pa = reinterpret_cast<int>(&a);
	cout << pa << endl;

2.1.3 const_cast

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

	//去掉const属性
	//这里要加上volatile关键字,保持内存的可见性,为什么呢?
	//因为当我们定义出const常变量的时候,编译器默认我们这个
	//常变量是不能被修改的,所以编译器为了提高效率就把这个常变量
	//放到了寄存器中(因为寄存器快),在下一次访问这个常变量的时候
	//就不会去内存中获取了,直接去寄存器中取,所以如果我们通过类
	//型转化的方式改变了这个常变量的属性,使它能够被修改,然后
	//修改这个变量,即在内存中修改了这个变量,但是由于编译器的优化,
	//在访问的时候取寄存器中获取数据,所以访问到的依然是原来的值,
	//这就等于是没有去掉const属性,所以我们要加上volatile关键字
	//修饰这个常变量,作用就是告诉编译器不要把const变量放到寄存器中,
	//每一次访问的时候就去内存中读取,这样的话const变量强转了,并且
	//修改了之后我们就能访问到新的值了
	volatile const int c = 12;
	int* d = const_cast<int*>(&c);
	*d = 10;//c也变成了10

没加volatile关键字时:

在这里插入图片描述
加了volatile关键字时:
在这里插入图片描述
所以C语言中如果需要间接地修改const变量的值也要加上volatile保持内存可见性。

2.1.4 dynamic_cast

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

注意:

  1. dynamic_cast只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回nullptr
class parent
{
public:
	virtual void func()
	{
		cout << "parent::func()" << endl;
	}
private:
	int _a = 10;
};

class son :public parent
{
private:
	int _b = 20;
};

void Print(parent* p)
{
	//如果p是指向子类的指针,那么能转化成功
	//如果p是指向父类的指针,则转化失败
	son* s = dynamic_cast<son*>(p);
	if (s)
	{
		cout << "转换成功" << endl;
	}
	else
	{
		cout << "转化失败" << endl;
	}
}

int main()
{
	parent* par = new parent;
	son* s = new son;
	Print(par);
	//s->func();
	//par = dynamic_cast<parent*>(s);
	//if (par)
	//{
	//	par->func();
	//}

	return 0;
}

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

三、RTTI(了解)

RTTI:Run-time Type identification的简称,即:运行时类型识别。C++通过以下方式来支持RTTI:

  1. typeid运算符
  2. dynamic_cast运算符
  3. decltype

四、特殊的类型转换

相信大家对内置类型转自定义类型都不陌生了,例如像字符串这样的单参数的构造函数能支持隐式类型的转换,
string str=“abc”,但是反过来自定义类型隐式类型转换成内置类型的操作你又有没有见过呢?例如以下的代码:

class A
{
public:
	A(int a = 10)
		:_a(a)
	{}

	//定义类型转换,A类可以转换成int
	//注意:这里不能加explicit,否则就无法从A类型转换成int类型,
	//否则会禁止隐式类型的转化,
	//因为重载了operator bool,所以在这里会调用operator bool
	operator int()
	{
		return _a;
	}

	operator bool()
	{
		if (_a == 5)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	void print()const
	{
		cout << _a << endl;
	}

private:
	int _a;
};

int main()
{
	A a = 20;
	//这里的自定义类型A->int,原因是我们在A类中重载了operator int()
	//这里本质是a调用了operator int()函数,其实是int b = a.operator int()这样子写的,
	//因为支持隐式类型转换,所以可以直接写成以下形式
	int b = a;

	cout << b << endl;

	return 0;
}

void func(parent* p)
{
	son* s = dynamic_cast<son*>(p);
	if (s)
	{
		cout << "转换成功" << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}

class A
{
	friend istream& operator>>(istream& in, A& a);
	friend ostream& operator<<(ostream& out, A& a);

public:
	A(int a = 10)
		:_a(a)
	{}

	operator int()
	{
		return _a;
	}

	operator bool()
	{
		if (_a == 5)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	void print()const
	{
		cout << _a << endl;
	}

private:
	int _a;
};

istream& operator>>(istream& in, A& a)
{
	in >> a._a;
	return in;
}

ostream& operator<<(ostream& out, A& a)
{
	out << a._a << endl;
	return out;
}

int main()
{
	A a = 0;
	//这里只是模拟实现一下cin的结束条件,但是库里面的cin是
	//通过设置标志位判断是否结束的,这里的简单实现是当我们
	//输入5的时候就结束cin
	while (cin >> a&&a.operator bool())
	{
		a.print();
	}

	return 0;
}

以上就是今天想要跟大家分享的内容了,你学会了吗?如果感觉到有所收获,那么点点赞,点点关注呗,后期还会持续更新C++的相关知识哦,我们下期见!!!

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

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

相关文章

【Unity ShaderGraph】| 如何快速制作一个 马赛克效果 实战

前言 【Unity ShaderGraph】| 如何快速制作一个 马赛克效果 实战一、效果展示二、马赛克效果四、应用实例 前言 本文将使用Unity 的ShaderGraph制作一个马赛克的效果&#xff0c;可以直接拿到项目中使用。对ShaderGraph还不了解的小伙伴可以参考这篇文章&#xff1a;【Unity S…

2022最新版-李宏毅机器学习深度学习课程-P25 Spacial Transformer Layer

data augmentation/spacial transformer CNN 并不能够处理影像放大缩小,或者是旋转的问题。所以在做影像辨识的时候,往往都要做 Data Augmentation&#xff0c;把你的训练数据截一小块出来放大缩小、把图片旋转&#xff0c;CNN 才会做到好的结果。 有一个架构叫 spacial Tran…

Ubuntu 22.04.3 LTS单机私有化部署sealos desktop

推荐使用奇数台 Master 节点和若干 Node 节点操作系统 :Ubuntu 22.04 LTS内核版本 :5.4 及以上配置推荐 :CPU 4 核 , 内存 8GB, 存储空间 100GB 以上最小配置 :CPU 2 核 , 内存 4GB, 存储空间 60GB 这里采用的Ubuntu 22.04.3 LTS 版本&#xff0c;Ubuntu 20.04.4 LTS这个版本…

iOS——Manager封装网络请求

在之前的项目里&#xff0c;我们都是把网络请求写在viewController的viewDidLoad&#xff0c;而实际中使用的时候并不能这么简单&#xff0c;对于不同的需要&#xff0c;我们需要有不同的网络请求。所以我们可以用单例模式创建一个全局的Manager类&#xff0c;用实例Manager来执…

微信朋友圈的高级玩法!你一定要知道!

我们都知道&#xff0c;朋友圈是一个社交平台&#xff0c;可以让我们和朋友们分享生活中的点滴&#xff0c;看到他们的动态。但你可能不知道&#xff0c;朋友圈其实有很多高级玩法&#xff0c;可以让你的社交体验更加丰富多彩。今天&#xff0c;就让我们一起来看看朋友圈的那些…

协同办公系统OA实施过程中需要注意的细节

随着企业对于高效、便捷的办公方式的需求增加&#xff0c;协同办公系统OA正逐渐成为企业信息化建设的热门选择。然而&#xff0c;协同办公系统OA的实施并非一蹴而就&#xff0c;需要企业在实施过程中注意一系列的细节。 一、规划与需求分析 企业应根据自身的业务需求和发展战略…

天津滨海新区城市轨道交通电能管理系统方案与实施方案

【摘要】&#xff1a;介绍天津滨海新区轨道交通项目建设电能管理系统的系统架构、功能组成和实施方案。在借鉴其他城市轨道交通项目电能管理系统的基础上,结合天津滨海新区轨道交通建设的具体情况&#xff0c;对系统组网方案、测量表计设置原则、与通风空调节能系统和照明节能系…

20231017定时任务

1. 构建定时任务 表达式生成 在线Cron表达式生成器 1.1 启动类 1.2 测试范例 描述: 1,将该类用Component描述,交给spring管理. 2,定时任务方法用Scheduled&#xff0b;cron表达式描述 2. 定时任务的弊端和优化方案 1.假如有一个定时任务,每小时检查关闭超时未支付订单,当10…

螺纹快速接头在卫浴行业中的应用提高产量降低生产成本

螺纹快速接头在卫浴行业主要用于上下水测试和密封性测试&#xff0c;可以快速密封连接待测产品和水管。取代之前的工人手拧编织管六角螺母的方式&#xff0c;方便快捷&#xff0c;密封性好&#xff0c;产品测试更稳定。 卫浴行业产品必须具备很好的密封性&#xff0c;防止在实际…

GeoServer改造Springboot启动四(解决post接口方法无法用@requestbody为入参的请求)

1、修改源码4 解决问题:解决Controller接口post方法(如图 19)无法用@requestbody为入参的 json数据进行请求,用swagger请求示例如图 20,具体错误呈现如图 21。 图 19Controller接口示例 图 20post接口请求示例 图 21post接

CEC2013(MATLAB):​白鲸优化算法(Beluga whale optimization,BWO)​求解CEC2013

一、白鲸优化算法&#xff08;Beluga whale optimization&#xff0c;BWO&#xff09; 白鲸优化算法&#xff08;Beluga whale optimization&#xff0c;BWO&#xff09;由Changting Zhong等人于2022年提出&#xff0c;该算法模拟了白鲸游泳&#xff0c;觅食和“鲸鱼坠落”行为…

Qt绘图 day9

Qt绘图 day9 基本绘图流程 Qt的绘制系统支持在屏幕和打印设备上使用相同的API进行绘制&#xff0c;主要基于QPainter、QPaintDevice和QPaintEngine类。 QPainter&#xff1a;用于执行绘图操作QPaintDevice&#xff1a;用于二维空间的抽象QPainEngine&#xff1a;提供绘图器在不…

低学历可以学python吗?

低学历可以学python吗&#xff1f; 看不到前途&#xff0c;是不是自己对以后工作就业的事情感到比较迷茫呢&#xff1f; 是不知道企业要求哪些知识&#xff0c;想要的是什么样能力的人&#xff1f; 最近很多小伙伴找我&#xff0c;说想要一些c语言资料&#xff0c;然后我根据…

Windows 钉钉多开 dingtalkRC版

亲测可用 下载链接&#xff1a; https://dtapp-pub.dingtalk.com/dingtalk-desktop/win_installer/RC/DingTalk_v6.5.20-RC.7229101.exe

基于SpringBoot的医疗预约服务管理系统

基于SpringBootVue的医疗预约服务管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登陆界面 管理员界面 医生界面 会员界面 摘要 基于SpringBoot的…

计算机网络 | 应用层

计算机网络 | 应用层 计算机网络 | 应用层应用层概述网络应用模型客户/服务器模型&#xff08;Client/Server&#xff0c;C/S&#xff09;P2P模型&#xff08;Peer-to-Peer&#xff09; 域名系统&#xff08;DNS&#xff09; 参考视频&#xff1a;王道计算机考研 计算机网络 参…

【Interview】拟牛顿求一个数的平方根

如何求一个数的平方根&#xff1f; - 一点点算法的文章 - 知乎 牛顿迭代法的思路是通过切线方程与x轴的 交点&#xff0c;逐渐迭代收敛到一个数的平方根。 我们要求m的平方根&#xff0c;构造函数 用图1进行简单说明&#xff1a; 初始化选A点&#xff0c;求切线&#xff0c;…

Windows11家庭版没有本地组策略编辑器解决

1. 新建一个文本文件将下面代码粘到里面&#xff0c;保存后修改后缀为.cmd或者.bat echo off pushd "%~dp0"dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >List.txt dir /b C:\Windows\servicing\Packa…

开路、断路和短路区别

文章目录 开路和断路击穿电源短路、用电器短路、对地短路和对电源短路 开路和断路 开路和断路是电路中两种用于描述电流流动情况的状态。 两者易混淆&#xff0c;常被混淆使用&#xff0c;但是它们还是有所不同。 开路表示电路中存在一个断链&#xff0c;电流无法从一个点流到…

【MultiOTP】在Linux上使用MultiOTP进行SSH登录

在前面的文章中【FreeRADIUS】使用FreeRADIUS进行SSH身份验证已经了解过如何通过Radius去来实现SSH和SUDO的登录&#xff0c;在接下来的文章中只是将密码从【LDAP PASSWORD Googlt OTP】改成了【MultiOTP】生成的passcode&#xff0c;不在需要密码&#xff0c;只需要OTP去登录…