C++基础(二十四):C++的类型转换

         C++ 的类型转换(Type Casting)用于在不同类型之间转换数据。主要有四种方式:隐式转换由编译器自动完成;C 风格转换使用 (new_type)expression 语法,功能强大但不安全;static_cast 用于相关类型之间的显式转换,较为安全;dynamic_cast 主要用于多态类型的安全转换;const_cast 用于修改对象的常量性;reinterpret_cast 进行低级别的位模式转换,需谨慎使用。通过这些转换,开发者可以灵活处理不同类型的数据。

目录

一、C语言中的类型转换

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

三、C++强制类型转换

3.1 static_cast

3.2 reinterpret_cast

3.3 const_cast

​编辑 3.4 dynamic_cast

四、RTTI(了解)


一、C语言中的类型转换

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

        可见,C语言支持相近类型的隐式类型转换(相近类型也就是意义相似的类型),也支持不相近类型的强制转换(不相近类型也就是意义差别很大的类型)。缺陷: 转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。

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

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

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

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

三、C++强制类型转换

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

  1. static_cast
  2. reinterpret_cast
  3. const_cast
  4. dynamic_cast

3.1 static_cast

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

int main()
{
    double d = 12.34;
    int a = static_cast<int>(d);
    cout<<a<<endl;
    return 0;
}

3.2 reinterpret_cast

       reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型,对应C语言中大部分的强制类型转换(不相近类型)。

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

3.3 const_cast

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

#include <iostream>
using namespace std;

void Test()
{
    const int a = 2;                 // a 是一个常量整数,值为 2
    int* p = const_cast<int*>(&a);   // p 是一个指向整数的指针,指向 a 的地址
    *p = 3;                          // 将 a 的值修改为 3
    cout << *p << endl;              // 输出指针 p 所指向的值
    cout << a << endl;               // 输出 a 的值,由于C++是以常量为主的,他会直接进行替换成2,不会去内存取值!
}

int main()
{
    Test();

    return 0;
}

//如果想要编译器禁止做这个优化,加上volatile关键字
 volatile const int a = 2;    

 

 3.4 dynamic_cast

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

  1. 向上转型:子类对象/指针/引用->父类对象/指针/引用(这个过程发生切片,语法天然支持,不需要转换,赋值兼容规则)
  2. 向下转型:父类对象/指针/引用->子类对象/指针/引用(用dynamic_cast转型是安全的)

注意:

1. dynamic_cast只能用于父类含有虚函数的类;

2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

#include <iostream>
using namespace std;

class A
{
public:
	virtual void f() 
	{

	}
};


class B : public A
{

};


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

注意:

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

四、RTTI(了解)

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

typeid 运算符是 C++ 语言中用于获取对象类型信息的运算符。它是运行时类型识别(RTTI)的一个部分。typeid 运算符返回一个 type_info 对象的引用,该对象包含被检查类型的具体信息。

#include <iostream>
#include <typeinfo>

int main() {
    int a = 5;
    std::cout << "Type of a: " << typeid(a).name() << std::endl;
    return 0;
}

在这个例子中,typeid(a) 返回一个 type_info 对象,该对象描述变量 a 的类型。name() 成员函数返回一个 C 风格的字符串,表示类型的名称。

至此,这一讲内容介绍完毕,内容简单,星光不问赶路人,加油吧,感谢阅读,如果对此专栏感兴趣,点赞加关注!

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

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

相关文章

Apple Intelligence将如何重新定义iPhone上的Siri使用方式|TodayAI

经过多年的讨论和批评&#xff0c;苹果&#xff08;Apple&#xff09;终于在今年秋季承诺推出更智能版本的数字助理Siri。此次更新得益于苹果智能&#xff08;Apple Intelligence&#xff09;&#xff0c;这是公司推出的生成式AI产品&#xff0c;并与OpenAI合作开发。 Siri将迎…

FPGA CFGBVS 管脚接法

说明 新设计了1个KU040 FPGA板子&#xff0c;回来之后接上JTAG FPGA不识别。做如下检查&#xff1a; 1、电源测试点均正常&#xff1b; 2、查看贴片是否有漏焊&#xff0c;检查无异常&#xff0c;设计上NC的才NC&#xff1b; 3、反复检查JTAG接线是否异常&#xff0c;贴片是…

linux 安装 RocketMQ 4.7

安装介绍 Centos 7RocketMQ 4.7JDK 1.8 (安装JDK参考)RocketMQ的官网地址&#xff1a; http://rocketmq.apache.orgGithub地址是 https://github.com/apach e/rocketmq 安装操作 下载RocketMQ RocketMQ运行版本下载地址&#xff1a; Rocketmq-all-4.7.1-bin-release.zip …

iOS ------ 消息传递和消息转发

一&#xff0c;消息传递 在OC中&#xff0c;传递消息就是在对象上调用方法。 相对于C语言的方法就“静态绑定”的函数&#xff0c;在编译器就决定了运行时所要调用的函数。在OC中&#xff0c;如果向某对象传递消息&#xff0c;就会使用动态绑定机制来决定需要调用那个方法。调…

深度学习新动向!液态神经网络拿下Nature子刊,19个神经元驾驶一辆车!

还记得麻省理工提出的脑启发AI系统吗&#xff1f;灵感来自线虫大脑中的神经计算&#xff0c;通过使用19个节点的液态神经网络&#xff0c;实现自动驾驶控制&#xff0c;比常规神经网络方法减少了数万倍神经元&#xff0c;成功登上Nature子刊&#xff01; 这种液态神经网络具有…

数据结构(5.2_2)——二叉树的性质

常见考点1: 设非空二叉树中度为0、1和2的结点个数分别为n0、n1和n2&#xff0c;则n0n21(叶子结点比二分支结点多一个) 常见考点2&#xff1a; 二叉树第一层至多右 有个结点(i>1) m叉树第一层至多右 有个结点(i>1) 常见考点3&#xff1a; 高度为h的二叉树至多有个结点…

NineData全面支持PostgreSQL可视化表结构设计

“PostgreSQL 是最像 Oracle 的开源关系型数据库“&#xff0c;也正因为如此&#xff0c;很多企业都青睐 PostgreSQL&#xff0c;拿它当成 Oracle 的替代品。所以毫无疑问&#xff0c;目前 PostgreSQL 在企业中非常常见。 对于直接接触 PostgreSQL 的开发人员而言&#xff0c;…

# Redis 入门到精通(五)-- redis 持久化(2)

Redis 入门到精通&#xff08;五&#xff09;-- redis 持久化&#xff08;2&#xff09; 一、redis 持久化–save 配置与工作原理 1、RDB 启动方式&#xff1a;反复执行保存指令&#xff0c;忘记了怎么办&#xff1f;不知道数据产生了多少变化&#xff0c;何时保存&#xff1…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【获取密钥属性(ArkTS)】

获取密钥属性(ArkTS) HUKS提供了接口供业务获取指定密钥的相关属性。在获取指定密钥属性前&#xff0c;需要确保已在HUKS中生成或导入持久化存储的密钥。 开发步骤 指定待查询的密钥别名keyAlias&#xff0c;密钥别名最大长度为64字节。调用接口[getKeyItemProperties]&…

Linux下的C++编程(2)——动态库

为什么要使用动态库&#xff1f; 在实际工作工作&#xff0c;常常需要给予其他人自己的库文件&#xff0c;但是&#xff0c;我们只想让其他人使用我们的库文件&#xff0c;而不想让其他人知道我们具体代码&#xff0c;所以就引入了动态库的概念&#xff0c;使用动态库可以让使…

2.10、matlab中字符、数字、矩阵、字符串和元胞合并为字符串并将字符串以不同格式写入读出excel

1、前言 在 MATLAB 中&#xff0c;可以使用不同的数据类型&#xff08;字符、数字、矩阵、字符串和元胞&#xff09;合并为字符串&#xff0c;然后将字符串以不同格式写入 Excel 文件。 以下是一个示例代码&#xff0c;展示如何将不同数据类型合并为字符串&#xff0c;并以不…

AQS源码解析(ReentrantLock)

什么是AQS:Juc中的大多数同步器都是围绕着一些相同的基础行为&#xff0c;比如等待队列&#xff0c;条件队列&#xff0c;共享&#xff0c;独占获取变量这些行为&#xff0c;抽象出来就是基于AQS&#xff08;AbstractQueuedSynchronizer&#xff09;实现的。所以可以把AQS看成这…

windows qt编译报错 无法打开包括文件: “EGL/egl.h”: No such file or directory

windows mingw32 qt creator QtAV 推荐ffmpeg依赖包 QT5.14.2 如果出现&#xff1a;无法打开包括文件: “EGL/egl.h”: No such file or directory 可能是Qt6的问题.在QT5上安装。 编译步骤&#xff1a; git clone https://github.com/wang-bin/QtAV.git cd QtAV &&…

Mysql-错误处理: Found option without preceding group in config file

1、问题描述 安装MYSQL时&#xff0c;在cmd中“初始化”数据库时&#xff0c;输入命令&#xff1a; mysqld --initialize --consolecmd报错&#xff1a; D:\mysql-5.7.36-winx64\bin>mysql --initialize --console mysql: [ERROR] Found option without preceding group …

Qt基础 | Qt全局定义 | qglobal头文件中的数据类型、函数、宏定义

文章目录 一、数据类型定义二、函数三、宏定义 QtGlobal头文件包含了 Qt 类库的一些全局定义 &#xff0c;包括基本数据类型、函数和宏&#xff0c;一般的Qt类的头文件都会包含该文件。 详细内容可参考&#xff1a;https://doc.qt.io/qt-5/qtglobal.html 一、数据类型定义 为了…

【扩散模型(五)】IP-Adapter 源码详解3-推理代码

系列文章目录 【扩散模型&#xff08;一&#xff09;】中介绍了 Stable Diffusion 可以被理解为重建分支&#xff08;reconstruction branch&#xff09;和条件分支&#xff08;condition branch&#xff09;【扩散模型&#xff08;二&#xff09;】IP-Adapter 从条件分支的视…

花几千上万学习Java,真没必要!(十一)

1、跳转控制语句&#xff1a; 测试代码1&#xff1a; package com.continuetest; public class ControlFlowDemo { // break语句 public void demonstrateBreak() { for (int i 0; i < 10; i) { if (i 5) { break; // 当i等于5时&#xff0c;跳出循环 } System.o…

【眼疾病识别】图像识别+深度学习技术+人工智能+卷积神经网络算法+计算机课设+Python+TensorFlow

一、项目介绍 眼疾识别系统&#xff0c;使用Python作为主要编程语言进行开发&#xff0c;基于深度学习等技术使用TensorFlow搭建ResNet50卷积神经网络算法&#xff0c;通过对眼疾图片4种数据集进行训练&#xff08;‘白内障’, ‘糖尿病性视网膜病变’, ‘青光眼’, ‘正常’&…

项目管理进阶之RACI矩阵

前言 项目管理进阶系列续新篇。 RACI&#xff1f;这个是什么矩阵&#xff0c;有什么用途&#xff1f; 在项目管理过程中&#xff0c;如Team规模超5以上时&#xff0c;则有必要采用科学的管理方式&#xff0c;满足工作需要。否则可能事倍功半。 Q&#xff1a;什么是RACI矩阵 …