【C++】类型转换


目录

一、C语言中的类型转换

二、C++中的类型转换

1.static_cast

2.reinterpret_cast

3.const_cast

4.dynamic_cast

三、RTTI

1.typeid运算符

2. decltype


一、C语言中的类型转换

C 语言中,如果 赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与 接收返回值类型不一致时,就需要发生类型转化 C 语言中总共有两种形式的类型转换: 隐式类型 转换和显式类型转换
 
1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
2. 显式类型转化:需要用户自己处理
int main()
{
	//隐式类型转换
	int i = 5;
	double d = i;
	//显式类型转换
	int* pi = &i;
	int address = (int)pi;

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

二、C++中的类型转换

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

1.static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。
  
例如:
我们可以用于将 double 类型转化成int类型,但是不可以将 double *类型转化成int类型。
int main()
{
	double d = 5.32;
	int i = static_cast<int>(d);

	double* pd = &d;
	int di = static_cast<int>(pd);
	cout << di << endl;
	return 0;
}

     

2.reinterpret_cast

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

 

例如:

我们上面无法将double*转化成int类型,用reinterpret_cast就可以实现。

int main()
{
	double d = 5.32;
	double* pd = &d;
	int di = reinterpret_cast<int>(pd);
	cout << di << endl;
	return 0;
}

   

3.const_cast

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

例如:

将const类型的常变量转化为没有const属性的类型

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

	cout << a << endl;
	cout << *p << endl;
	return 0;
}

看到结果,很多人可能就会好奇了,怎么还会打印不同的结果呢?

这是因为,我们用const修饰a类型之后,编译器认为a之后都不会改变,就将a读取到寄存器中,之后读取a的数据都是用存储在寄存器中的数据。当我们用*p修改了a在内存中的值之后,打印a是打印寄存器中a的值,打印*p则是内存中a的值。所以结果会不同。

拓展:volatile

volatile是一个关键字,作用是保持内存的可见性,也就是每次读取数据都会从内存中读取。

int main()
{
	volatile const int a = 2;
	int* p = const_cast<int*> (&a);
	*p = 3;

	cout << a << endl;
	cout << *p << endl;
	return 0;
}

    

4.dynamic_cast

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
 
向上转型:子类对象指针 / 引用 -> 父类指针 / 引用 ( 不需要转换,赋值兼容规则 )
向下转型:父类对象指针 / 引用 -> 子类指针 / 引用 ( dynamic_cast 转型是安全的 )
 
注意:
1. dynamic_cast 只能用于父类含有虚函数的类(如果是子类含有虚函数而父类不具有,那么无法转换)
2. dynamic_cast 会先检查是否能转换成功,能成功则转换,不能则返回 0
   

 代码示例:

当我们用强制类型转换的时候,是可能会发生越界问题的。

class Father
{
public:
	virtual void f(){}
private:
	int _a;
};

class Child :public Father
{
public:
	int _b = 2 ;
};

void Func(Father* f)
{
	Child* ch = (Child*)f;
	cout << ch->_b << endl;
}

int main()
{
	Father* th = new Father;
	Child* ch = new Child;
	Func(th);
	Func(ch);
	return 0;
}

    

 我们再用dynamic_cast来将父类转换成子类

class Father
{
public:
	virtual void f(){}
private:
	int _a;
};

class Child :public Father
{
public:
	int _b = 2 ;
};

void Func(Father* f)
{
	Child* ch = dynamic_cast<Child*>(f);
	if (ch == 0)
	{
		cout << "转换失败" << endl;
		return;
	}
	cout << ch->_b << endl;

}

int main()
{
	Father* th = new Father;
	Child* ch = new Child;
	Func(th);
	Func(ch);
	return 0;
}

 我们可以看到,会出现越界问题的就会转化失败返回0。

这样使得我们的程序更加安全。


三、RTTI

RTTI Run-time Type identifification 的简称,即:运行时类型识别。
 
C++ 通过以下方式来支持 RTTI
1. typeid运算符
2. dynamic_cast运算符
3. decltype

  

1.typeid运算符

作用:一般我们使用typeid来查看变量的类型。 

格式:typeid(变量).name()

代码示例: 

int main()
{
	int a = 0;
	cout << typeid(a).name() << endl;
	return 0;
}

2. decltype

作用:复制变量的类型作为使用。

格式:decltype(变量) + 新变量名

int main()
{
	int a = 0;
	decltype(a) b = 10;
	cout << b << endl;
	return 0;
}

我们有时候可能会忘记了某个变量的名字,但是查找定义又十分麻烦,为了便于创建一个同类型的变量,我们可以使用decltype。

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

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

相关文章

什么是域控服务器?域控服务器功能?部署域控需要考虑因素?域控组策略功能?

一、什么是域控制服务器&#xff1f; 域控制器&#xff08;Domain Controller&#xff09;是在Windows Server操作系统上运行的一个服务角色&#xff0c;它用于管理和控制一个或多个计算机的安全策略、用户身份验证和授权等任务。域控制器通常是用于企业网络中的主要身份验证和…

macOS Sonoma 14beta With OpenCore 0.9.3 and winPE双引导分区黑苹果原版镜像

镜像特点&#xff08;原文地址&#xff1a;http://www.imacosx.cn/113888.html&#xff09; 完全由黑果魏叔官方制作&#xff0c;针对各种机型进行默认配置&#xff0c;让黑苹果安装不再困难。系统镜像设置为双引导分区&#xff0c;全面去除clover引导分区&#xff08;如有需要…

华为OD机试真题 JavaScript 实现【IPv4地址转换成整数】【2023 B卷 100分】

一、题目描述 存在一种虚拟 IPv4 地址&#xff0c;由4小节组成&#xff0c;每节的范围为0~255&#xff0c;以#号间隔&#xff0c; 虚拟 IPv4 地址可以转换为一个32位的整数&#xff0c;例如&#xff1a; 128#0#255#255&#xff0c;转换为32位整数的结果为2147549183&#xff0…

vue制作自己的组件库(仿ElementUI)

1.首先自己创建个新的vue项目&#xff0c;之后更改下目录形式&#xff0c;将src文件更改为examples&#xff0c;这里是专门放组件展示的md文件&#xff0c;packages文件里是放自己写的组件代码 2.然后是开始配置vue.config.js文件 &#xff0c;其中md-loader是读取md文件的相关…

【C/C++】带你快速掌握 使用—增强for(范围for循环)

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

MySQL 存储过程

1 什么是存储过程 MySQL 5.0 版本开始支持存储过程存储过程&#xff08;Stored Procedure&#xff09;是一种在数据库中存储复杂程序&#xff0c;以便外部程序调用的一种数据 库对象。存储过程是为了完成特定功能的SQL语句集&#xff0c;经编译创建并保存在数据库中&#xff0…

【c语言进阶】深入挖掘数据在内存中的存储

深入挖掘数据在内存中的存储 数据类型介绍数据类型基本分类及其大小 整形在内存中的存储方式原码、反码、补码大小端介绍判断一个系统是大端还是小端 char与unsigned char值范围与图解整形存储相关练习题 浮点数在内存中的存储方式浮点数存储规则案列 结语 铁汁们&#xff0c;今…

访问修饰符private,default,protected,public访问等级区别

private&#xff1a;private是最严格的访问修饰符&#xff0c;它将成员声明为私有的。私有成员只能在声明它们的类内部访问&#xff0c;其他类无法直接访问私有成员。这样可以确保数据的封装性和安全性。 default&#xff08;默认&#xff09;&#xff1a;如果没有明确指定访问…

Java调用Pytorch实现以图搜图(附源码)

Java调用Pytorch实现以图搜图 设计技术栈&#xff1a; 1、ElasticSearch环境&#xff1b; 2、Python运行环境&#xff08;如果事先没有pytorch模型时&#xff0c;可以用python脚本创建模型&#xff09;&#xff1b; 1、运行效果 2、创建模型&#xff08;有则可以跳过&#xf…

AI实战营:目标检测与MMDetection

目录 目标检测的基本范式 什么是目标检测 目标检测 vs 图像分类 目标检测 in 人脸识别 目标检测 in 智慧城市 ​编辑​编辑 目标检测 in 自动驾驶 目标检测 in 下游视觉任务 目标检测技术的演进 基础知识 框、边界框&#xff08;Bounding Box&#xff09; 交并比…

计算机网络填空题

我会写下自己的答案和理解 希望自己可用在学习中体会到快乐&#xff0c;而不是麻木。 1. 网络协议三要素中语义是指 需要发出何种控制信息&#xff0c;完成何种动作以及做出何种响应 1.在计算机网络中要做到有条不紊的交换数据&#xff0c;就必须遵守一些事…

组件更新的底层逻辑

第一种更新&#xff1a;组件更新的逻辑&#xff0c;当修改了相关状态&#xff0c;组件会更新 1.触发shouldComponentUpdate 周期函数:是否允许更新 shouldComponentUpdate(nextProps, nextState) { // nextState: 存储要修改的最新状态 // this. state:存储的还是修改前的状态…

闲置APP小程序开发 你不喜欢的可能正是别人需要的

生活中我们常常会产生各种闲置物品&#xff0c;尤其是对于有宝宝的家庭来说&#xff0c;孩子小的时候可能会添置各种玩具、婴儿车或者是别的用品&#xff0c;随着孩子渐渐长大&#xff0c;这些东西都用不上了&#xff0c;但是扔了又觉得很可惜&#xff0c;留着又占地方&#xf…

RocketMQ5.x版本延迟消息被重放问题调查

一、问题 由于目标计划是将集群从4.9.x逐步升级至5.x&#xff0c;故目前先对一些不重要的集群进行升级测试。 但是在4.x的broker陆续升级至5.x的过程中&#xff0c;发现了延迟消息被重放的问题。 具体如下: 在升级时刷新后台监控&#xff0c;发现竟然有写入量&#xff1a; 即…

基于组件化开发思想的微信小程序开发框架

跨端框架的出现为小程序应用的开发带来了巨大的便利性和灵活性。它们提供了统一的开发方式、代码复用的能力&#xff0c;并且与小程序容器技术紧密结合&#xff0c;实现了一次编码、多端运行的目标。开发者可以根据项目需求和团队技术栈选择合适的跨端框架&#xff0c;从而在不…

11 GMM——高斯混合模型

文章目录 11 GMM——高斯混合模型11.1 模型介绍11.2 通过MLE估计参数11.3 EM求解 11 GMM——高斯混合模型 11.1 模型介绍 从几何角度来说&#xff1a; 高斯混合模型表示&#xff1a;加权平均——由多个高斯分布混合叠加而成&#xff0c;如图 公式可以表达为&#xff1a; p…

基于XC7Z100的PCIe采集卡(GMSL FMC采集卡)

GMSL 图像采集卡 特性 ● PCIe Gen2.0 X8 总线&#xff1b; ● 支持V4L2调用&#xff1b; ● 1路CAN接口&#xff1b; ● 6路/12路 GMSL1/2摄像头输入&#xff0c;最高可达8MP&#xff1b; ● 2路可定义相机同步触发输入/输出&#xff1b; 优势 ● 采用PCIe主卡与FMC子…

安卓大作业 书籍列表APP

系列文章 安卓大作业 书籍列表APP 文章目录 系列文章1&#xff0e;背景2&#xff0e;功能3. 源代码获取 1&#xff0e;背景 我做的项目是一个可以查看到书籍列表以及详情效果的内容&#xff0c;主要使用到的技术有Intent数据传递以及数据库存储的应用&#xff0c;其次使用的组…

Qt线程的几种使用方法

目录 引言使用方法重写QThread::run()moveToThreadQRunnable使用QtConcurrent使用 完整代码 引言 多线程不应该是一个复杂而令人生畏的东西&#xff0c;它应该只是程序员的一个工具&#xff0c;不应该是调用者过多记忆相关概念&#xff0c;而应该是被调用方应该尽可能的简化调…

Linux教程——常见Linux发行版本有哪些?

新手往往会被 Linux 众多的发行版本搞得一头雾水&#xff0c;我们首先来解释一下这个问题。 从技术上来说&#xff0c;李纳斯•托瓦兹开发的 Linux 只是一个内核。内核指的是一个提供设备驱动、文件系统、进程管理、网络通信等功能的系统软件&#xff0c;内核并不是一套完整的…
最新文章