[cpp进阶]C++类型转换

news2024/11/17 17:46:23

文章目录

  • C语言的类型转换
  • 为什么C++需要四种类型转换
  • C++强制类型转换
    • static_cast
    • reinterpret_cast
    • const_cast
    • dynamic_cast
    • explicit
  • RTTI

C语言的类型转换

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

隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
显式类型转化:需要用户自己处理

int main()
{
	// 隐式类型转换
	int i = 1;
	double d = i;
	printf("%d %.2f\n", i, d);

	// 强制类型转换
	int* p = &i;
	int address = (int)p;
	printf("%p %d\n", p, address);

	return 0;
}

为什么C++需要四种类型转换

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

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

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


C++强制类型转换

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

static_cast

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

int main()
{
	double d = 12.34;
	int i = static_cast<int>(d);
	cout << i << endl;

	return 0;
}

但是static_cast不能用于两个不相关类型之间的转换:

int* p = &i;
int address = static_cast<int>(p);

在这里插入图片描述


reinterpret_cast

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

int main()
{
	int i = 10;
	int* p = &i;
	int* address = reinterpret_cast<int*>(p);

	return 0;
}

reinterpret_cast有很bug的用法,reinterpret_cast可以让编译器以FUNC的视角看待DoSomething函数并调用:

typedef void (*FUNC)();
int DoSomething(int i)
{
	cout << "DoSomething" << endl;
	return 0;
}

int main()
{
	FUNC f = reinterpret_cast<FUNC>(DoSomething);
	f();

	return 0;
}

运行结果:

在这里插入图片描述


const_cast

const_cast用于删除变量的const属性,转换后就可以对const变量的值进行修改:

int main()
{
	const int a = 10;
	int* p = const_cast<int*>(&a);

	*p = 20;
	cout << *p << endl;

	return 0;
}

运行结果:

在这里插入图片描述
但是,我们如果同时打印原变量a,我们发现a的值并没有改变:
在这里插入图片描述

这是因为编译器做了优化,在发现变量a是const属性时,默认变量a不会被改变,就将变量a存放到寄存器中,打印出来的值是直接从寄存器取出来的值,修改的是内存中的值,如果不想让编译器做出优化,可以使用volatile关键字对变量进行修饰,在读取变量时就会从内存中读取:

在这里插入图片描述


dynamic_cast

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

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

当我们在函数中用父类的指针或引用接受参数时,接收的参数有可能指向父类对象也有可能指向子类对象,当接收的参数指向父类对象时,不需要做任何处理,当接收的参数指向子类对象时,有时就需要将该对象转换为原来的子类对象。

dynamic_cast可以做到将父类对象转换为子类对象,如果要转换的类型原本就是父类对象,返回nullptr,否则返回转换成功后的对象指针。

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

class B : public A
{};

void func(A* pa)
{
	B* pb = dynamic_cast<B*>(pa);
	if (pb == nullptr) {
		cout << "转换失败" << endl;
	}
	else {
		cout << "pb: " << pb << endl;
	}
}

int main()
{
	A a;
	B b;
	func(&a);
	func(&b);

	return 0;
}

实验结果:

在这里插入图片描述


explicit

explicit可以防止经过构造函数进行的隐式类型转换的发生。

class A
{
public:
	explicit A(int a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& a)
	{
		cout << "A(const A& a)" << endl;
	}
private:
	int _a;
};

int main()
{
	A a1(1);
	// 隐式转换-> A tmp(1); A a2(tmp);
	A a2 = 1;
}

在这里插入图片描述
实际上A a2 = 1;在底层会将1经由构造函数构造出一个对象,最后再将该对象赋给a2,explicit可以有效防止这种隐式类型转换。


RTTI

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

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

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

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

相关文章

使用lnmp与wordpress做1个外贸询盘网站

目录 lnmp安装 包安装 mysql元数据库 网路策略确认 iptables确认 mysql允许远程访问 wordpress下载安装 包安装 nginx配置 wordpress配置 初始化 astra&#xff0c;elementor和woocommerce插件 插件安装 模板选择 自定义网页 国内不兴建站&#xff0c;通常只有码…

openstack: nova : reset-state

https://github.com/openstack/python-novaclient 牵扯的两个project是&#xff1a;nova和python-novaclient&#xff1b; 这个命令从代码分析和实际使用上来看只是将nova数据库里的实例的状态更改&#xff1b;没有对实例做实质的操作。 https://docs.openstack.org/nova/pik…

01 C语言实现动态气泡碰撞和移动的效果,小球碰撞,Win7气泡壁纸,碰撞算法

C语言实现动态气泡碰撞和移动的效果 作者将狼才鲸创建日期2023-01-29 Git源码仓库地址&#xff1a;C语言实现动态气泡碰撞和移动的效果CSDN文章地址&#xff1a;01 C语言实现动态气泡碰撞和移动的效果 一、前言 想要实现多气泡相互碰撞的效果&#xff1b; 想着这种在Win7壁纸…

【Cloudera Manager】cdh集群ntp时钟同步问题

CM启动后集群界面出现时钟未同步问题在集群主机通过ntpstat命令查看&#xff0c;出现unsynchronised标识通过timedatectl命令&#xff0c;显示NTP synchronized: no以上说明确实没有同步时钟问题排查与解决首先查看ntp配置文件&#xff0c;cat /etc/ntp.confserver 172.X.X.X配…

万年历农历法定节假日数据查询工具

1.数据来源于百度搜索置顶日历&#xff1a; 2.代码&#xff1a; http调用及数据处理均采用了hutool, 也可以用别的工具。 hutool 依赖如下&#xff1a; <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><versio…

DNS 域名解析服务器详解以及相关实验

目录 一&#xff0c; 域名解析服务器的介绍 1&#xff0c; 因特网的域名结构 2&#xff0c; 域名服务器的类型划分 二&#xff0c;DNS 域名解析的过程 三&#xff0c;DNS 解析方式 四&#xff0c;搭建 DNS 服务器 1&#xff0c;使用命令yum install bind -y安装dns软件 2&#…

对于初学python的小白大佬们有什么建议吗?

我认为态度是一块重要的敲门砖。米卢说&#xff1a;“态度决定一切”。你对人生的态度是这个世界真正的试金石。对不同的事情要有不同的态度。而对待自学&#xff0c;认真就妥了。 首先要为自己设定一个目标&#xff0c;对于初学者&#xff0c;看书的话可以看《Head First Pyt…

几款考研必备软件 你还不知道吗?

几款考研必备软件 你还不知道吗? 英语单词软件推荐 背单词软件 墨墨背单词[推荐指数]⭐️⭐️⭐️⭐️⭐️ 科学高效抗遗忘方法,记录详细记忆行为数据,结合记忆反馈帮你记忆更加牢固 界面简洁舒适无广告,没有任何干扰,就算是强迫症也能使用的非常舒适 完美收集权威单词本,全…

哈佛大学庄小威团队破解衰老大脑的关键变化

“了解衰老是生物医学最重要的目标之一&#xff0c;同时这也是一个非常具有挑战性的问题。”哈佛大学终身教授庄小威说&#xff0c;“造成挑战的原因之一在于大脑非常复杂&#xff0c;细胞种类繁多&#xff0c;许多不同类型的神经元和非神经元细胞形成了复杂的相互作用网络。”…

一种二阶Biquad滤波器

一、首先给出biquad的Z变换函数为&#xff1a; 为了计算方便可对上式进行归一化处理&#xff0c;分子分母同时除以a0&#xff0c;则得出如下&#xff1a; 对应的差分方程为&#xff1a; 二、用户定义参数如下 #ifndef LN2 #define LN2 0.69314718055994530942 #endif #ifnde…

密码学技术导论篇

密码学技术前言基础术语不要使用保密的密码算法任何密码总有一天都会被破解对称密码&#xff08;共享秘钥密码&#xff09;AES总结公钥密码 --- 用公钥加密&#xff0c;私钥解密秘钥配送问题公钥密码中间人攻击认证单向散列函数--- 消息的指纹单向散列函数的实际应用单向散列函…

python接口自动化——unittest简介(详解)

简介 前边的随笔主要介绍的requests模块的有关知识个内容&#xff0c;接下来看一下python的单元测试框架unittest。熟悉 或者了解java 的小伙伴应该都清楚常见的单元测试框架 Junit 和 TestNG&#xff0c;这个招聘的需求上也是经常见到的。python 里面也有单元 测试框架-unitt…

Lua 垃圾回收

Lua 垃圾回收 参考至菜鸟教程。 Lua 采用了自动内存管理。 这意味着你不用操心新创建的对象需要的内存如何分配出来&#xff0c; 也不用考虑在对象不再被使用后怎样释放它们所占用的内存。 Lua运行了一个垃圾收集器来收集所有死对象&#xff08;即在Lua中不可能再访问到的对象&…

新能源——充电控制

一、交流充电——慢充 交流充电&#xff1a;电网输入给车辆的交流电&#xff0c;220V AC单向电或380V AC三相电。 车载充电机&#xff1a;交流电转化为直流电 二、直流充电——快充 三、充电模式 模式1——标准插座 模式2——带有交流电动汽车供电设备的标准插座 模式3——…

idea maven打包编译报错 java.lang.AssertionError: input.getType

今天使用idea打包编译maven项目&#xff0c;出现如下报错 构建报错时&#xff0c;最先显示的是这个报错。查了一圈下来&#xff0c;我的配置是没有问题的。 Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project…

WackoPicko通关教程

7.WackoPicko通关教程 首先进入网站&#xff0c;整体浏览网页&#xff0c;看网站的功能点 本着见框就插的原则&#xff0c;我们可以在搜索框进行查询 构造payload&#xff1a; <script>alert(/xss/)</script> 查看网站&#xff0c;成功触发弹窗 之后进入留言板…

45.Isaac教程--地图编辑器

地图编辑器 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录地图编辑器运行地图编辑器编辑现有地图层添加新的航点或多边形修改现有航点和多边形创建一个新的 WaypointMapLayer创建一个新的 PolygonMapLayer删除图层启用/禁用图层地图编辑…

【Python】request.session的cookie如何导入aiohttp._cookie_jar

request.session的cookie导入aiohttp._cookie_jar的教程 1.起因 我的 kook-valorant-bot 使用了两个开源库&#xff0c;用于riot账户的登录并获取token 其中最主要用的是基于aiohttp的floxay/python-riot-auth&#xff0c;但这个仓库不支持2fa用户&#xff08;开启了邮箱双重…

1999—2019年地级市人口变动数据(增长率\出生人口\死亡人口)

人口数据是我们在各项研究中最常使用的数据&#xff0c;而统计年鉴是人口数据的重要来源&#xff01;之前我们介绍过基于2000-2021年《中国城市统计年鉴》整理的1999年—2020年全国地级市的人口指标&#xff0c;包括户籍人口、常住人口、户数等指标&#xff08;可查看之前发布的…

史上最强strace命令详解

系列文章目录 文章目录系列文章目录前言一、strace是什么&#xff1f;二、strace怎么用总结前言 一、strace是什么&#xff1f; 按照 strace 官网的描述&#xff0c;strace 是一个可用于诊断、调试和教学的 Linux 用户空间跟踪器。我们用它来监控用户空间进程和内核的交互&…