【重走C++学习之路】26、类型转换

目录

一、C语言中的类型转换

二、C++中的四个类型转换

2.1 static_cast

2.2 dynamic_cast 

2.3 const_cast 

2.4  reinterpret_cast

2.5 总结 

结语


一、C语言中的类型转换

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

隐式类型转换(截断或提升):

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

double pi = 3.14159;
int truncatedPi = pi;  // 隐式转换,丢失小数部分
printf("Pi: %d\n", truncatedPi);  // 输出:3
return 0;

隐式转换可能导致数据丢失:在隐式类型转换中,可能会将一个较大范围的数据类型转换为一个较小范围的类型,导致数据丢失或精度损失。例如,double 转换为 int,会丢失小数部分。 

显式类型转换(强转)

用户自己手动强制转换变量类型

int num = 100;
int *int_ptr = #
void *void_ptr = (void*)int_ptr;  // 将int指针转换为void指针
int *new_int_ptr = (int*)void_ptr;  // 再将void指针转换回int指针

常见场景:

  • 数值类型转换
  • 指针类型转换
  • 函数参数类型适配

注意:

  • 数据截断风险
    在把大范围的数据类型转换为小范围的数据类型(例如从long转换为int)时,可能会导致数据截断。
  • 浮点精度丢失
    double类型转换为float类型时,可能会造成精度的损失。
  • 指针转换的危险性
    错误的指针类型转换可能会使程序崩溃或者产生未定义行为。

二、C++中的四个类型转换

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

1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失

2. 显式类型转换将所有情况混合在一起,代码不够清晰

因此C++提出了自己的类型转换风格,但C++中仍然可以使用C的类型转换。

在 C++ 里,为了进行类型转换,提供了四个功能不同的类型转换运算符,分别是static_castdynamic_castconst_cast以及reinterpret_cast

2.1 static_cast

static_cast主要用于进行良性转换,非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。它在编译阶段就会完成类型检查

使用格式:

static_cast<new_type>(expression)

使用场景:

  • 基本数据类型之间的转换
double d = 3.14;
int i = static_cast<int>(d);  // 把double类型转换为int类型,值为3
  • 子类到父类的向上转型
class Base {};
class Derived : public Base {};Derived d;
Base* b = static_cast<Base*>(&d);  // 安全的向上转型
  • 显式调用转换构造函数或者转换运算符
class Fraction 
{
public:Fraction(int num, int den = 1) : numerator(num), denominator(den) {}operator double() const { return (double)numerator / denominator; }
private:int numerator;int denominator;
};Fraction f(3, 4);
double d = static_cast<double>(f);  // 调用operator double()

2.2 dynamic_cast 

dynamic_cast主要用于进行安全的向下转型(将父类指针或引用转换为子类指针或引用),它会在运行时进行类型检查。如果转换不安全,对于指针会返回nullptr,对于引用则会抛出std::bad_cast异常。

使用格式:

dynamic_cast<new_type>(expression)

使用场景:

  • 安全的向下转型
class Base { virtual void dummy() {} };  // 必须有虚函数,才能进行RTTI
class Derived : public Base {};Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b);  // 转换成功,d不为nullptr
  • 交叉转型 
class Base { virtual void dummy() {} };
class Derived1 : public Base {};
class Derived2 : public Base {};
class Derived3 : public Derived1, public Derived2 {};Derived3* d3 = new Derived3;
Derived1* d1 = dynamic_cast<Derived1*>(d3);  // 转换成功
Derived2* d2 = dynamic_cast<Derived2*>(d1);  // 交叉转型,d2不为nullptr

2.3 const_cast 

const_cast专门用于修改类型的constvolatile属性,主要用于去除const限定(但要注意,通过这种方式修改原本为const的对象是未定义行为)。

使用格式:

const_cast<new_type>(expression)

使用场景:

  • 去除函数参数的const属性
void print(char* str) 
{printf("%s\n", str);
}const char* cstr = "Hello";
char* str = const_cast<char*>(cstr);  // 去除const限定
// print(cstr);  // 错误:不能将const char*传递给char*
print(str);     // 正确
  • const成员函数中修改对象状态
class Counter 
{
public:void increment() const {// count++;  // 错误:在const成员函数中不能修改成员变量const_cast<int&>(count)++;  // 正确:去除const限定}
private:int count;
};

2.4  reinterpret_cast

reinterpret_cast用于进行低级的类型重新解释,比如将指针转换为整数,或者将一种类型的指针转换为另一种不相关类型的指针。

使用格式:

reinterpret_cast<new_type>(expression)

使用场景:

  • 指针和整数之间的转换 
int* ptr = new int(10);
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);  // 将指针转换为整数
int* new_ptr = reinterpret_cast<int*>(addr);  // 将整数转换回指针
  • 不相关类型指针之间的转换
int num = 10;
int* int_ptr = &num;
char* char_ptr = reinterpret_cast<char*>(int_ptr);  // 将int指针转换为char指针
  • 函数指针类型的转换
typedef void (*FuncPtr)();int add(int a, int b) 
{ return a + b; 
}FuncPtr func = reinterpret_cast<FuncPtr>(add);  // 函数指针类型转换
// func();  // 调用会导致未定义行为

2.5 总结 

转换运算符主要用途安全性
static_cast基本类型转换、向上 / 向下转型(不进行运行时检查)中等
dynamic_cast安全的向下转型、交叉转型(运行时类型检查)
const_cast修改const/volatile属性低(容易导致未定义行为)
reinterpret_cast低级指针类型重新解释、指针与整数转换极低(非常危险)

结语

在实际编程中,优先使用C++风格的类型转换,避免使用C风格的强制类型转换,提高代码的安全性和可读性,这种用法会在Linux编程中见到。

下一篇将会介绍C++中IO流相关的知识,可以看作文件操作,有兴趣的朋友可以关注一下。

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

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

相关文章

kotlin 过滤 filter 函数的作用和使用场景

1. filter 函数的作用 filter 是 Kotlin 集合操作中的一个高阶函数&#xff0c;用于根据指定条件从集合中筛选出符合条件的元素。 作用&#xff1a;遍历集合中的每个元素&#xff0c;并通过给定的 lambda 表达式判断是否保留该元素。返回值&#xff1a;一个新的集合&#xff…

安卓程序打包与发布

一 配置编译信息 二 创建密钥

LeetCode算法题 (移除链表元素)Day15!!!C/C++

https://leetcode.cn/problems/remove-linked-list-elements/description/ 一、题目分析 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 今天的题目非常好理解&#xff0c;也就是要删除…

Scrapy框架之【Scrapy-Redis】分布式爬虫详解

Scrapy-Redis 介绍 Scrapy-Redis 是一个基于 Redis 实现的 Scrapy 分布式爬虫组件。Scrapy 本身是一个强大的 Python爬虫框架&#xff0c;但它默认是单进程单线程的&#xff0c;在面对大规模数据抓取任务时效率不高。Scrapy-Redis 则解决了这一问题&#xff0c;它允许你将 Scra…

Gradio全解20——Streaming:流式传输的多媒体应用(3)——实时语音识别技术

Gradio全解20——Streaming&#xff1a;流式传输的多媒体应用&#xff08;3&#xff09;——实时语音识别技术 本篇摘要20. Streaming&#xff1a;流式传输的多媒体应用20.3 实时语音识别技术20.3.1 环境准备和开发步骤1. 环境准备2. ASR应用开发步骤&#xff08;基于Transform…

使用xlwings将两张顺序错乱的表格进行数据核对

有如下一个excel表&#xff0c;姓名列的内容相同&#xff0c;顺序不同&#xff1b;月薪有部分内容不同。 目的&#xff1a;要找出哪几条月薪不同。 通常的做法&#xff0c;要使用excel的高级筛选。 在此&#xff0c;使用xlwings实现&#xff0c;在不同的内容上涂色。 代码如…

2025大模型安全研究十大框架合集(10份)

2025大模型安全研究十大框架合集的详细介绍&#xff1a; Anthropic AI信任研究框架 Anthropic于2024年10月更新的《安全责任扩展政策》(RSP)&#xff0c;提出了一个灵活的动态AI风险治理框架。该框架规定当AI模型达到特定能力时&#xff0c;将自动升级安全措施&#xff0c;如…

Qt/C++开发监控GB28181系统/云台控制/获取预置位信息/添加删除调用预置位

一、前言 之前用onvif已经完美实现了设备的云台控制和预置位的功能&#xff0c;这个基础功能在监控系统中是使用频率很高的&#xff0c;所有gb28181肯定也提供了这样的功能&#xff0c;很多人以为是通过包含xml数据&#xff0c;对应节点指定对应的动作来实现&#xff0c;其实不…

第T8周:猫狗识别

● 语言环境&#xff1a;Python3.8.8 ● 编译器&#xff1a;Jupyter Lab ● 深度学习环境&#xff1a;TensorFlow2.4.1 猫狗识别 一、前期工作1. 设置GPU 二、数据预处理1. 加载数据2.再次检查数据3.配置数据集 三、构建VG-16网络四、编译五、训练模型六、模型评估七、预测八、…

主流微前端框架比较

主流微前端框架比较 以下表格列出了当前主流微前端框架的核心对比信息,包括基本介绍、核心特性、适用场景、技术栈兼容性、优缺点、社区维护情况和典型应用案例等: 框架基本介绍核心特性与机制适用场景技术栈兼容性优缺点社区维护情况典型应用案例qiankun蚂蚁金服推出的生产…

大学生入学审核系统设计与实现【基于SpringBoot + Vue 前后端分离技术】

一、项目概述 1.1 项目背景 随着高校的不断扩招&#xff0c;传统的入学审核管理模式已不能满足大规模学生数据的处理需求。人工管理不仅效率低下&#xff0c;还容易出现疏漏。本系统通过信息化手段&#xff0c;提升入学审核过程中的数据管理和审批效率。 1.2 系统目标 系统…

云计算-容器云-服务网格Bookinfo

服务网格&#xff1a;创建 Ingress Gateway 将 Bookinfo 应用部署到 default 命名空间下&#xff0c;请为 Bookinfo 应用创建一个网 关&#xff0c;使外部可以访问 Bookinfo 应用。 上传ServiceMesh.tar.gz包 [rootk8s-master-node1 ~]# tar -zxvf ServiceMesh.tar.gz [rootk…

Spring 分批处理 + 冷热数据分离:历史订单高效迁移与数据清理实战

在实际业务中&#xff0c;随着时间推移&#xff0c;订单量持续增长&#xff0c;若未及时进行数据治理&#xff0c;会造成数据库膨胀、查询缓慢、性能下降等问题。为了实现数据分层管理和系统高性能运行&#xff0c;我们在项目中采用了“冷热数据分离 分批迁移 数据清理”的综…

新手SEO优化核心步骤

内容概要 对于SEO新手而言&#xff0c;建立系统化的优化框架是突破入门瓶颈的关键。SEO的核心在于通过技术手段与内容策略的结合&#xff0c;提升网站在搜索引擎中的可见性与用户价值。具体而言&#xff0c;新手需优先掌握关键词研究&#xff0c;明确目标用户的搜索意图&#…

C++ 之 【list的简介、list 的构造函数、iterator、容量操作、元素访问、增删查改与迭代器失效】

目录 1.list的介绍 2.list的使用 2.1 构造函数 2.2 iterator 的使用 2.3 容量操作 2.4 元素访问 2.5 增删查改 2.5.1头插头删与尾插尾删 2.5.2 insert 、erase 函数 2.5.3 clear、swap函数 2.5.4 关于find函数 3.迭代器失效 1.list的介绍 (1)list的底层通常实现为带…

Laravel Octane 项目加速与静态资源优化指南

Laravel Octane 项目加速与静态资源优化指南 一、Octane 核心加速配置 扩展安装与环境配置 composer require laravel/octane # 安装核心扩展‌php artisan octane:install # 生成配置文件&#xff08;选择 Swoole/RoadRunner 等服务器&#xff09;‌服务器参数调优‌ …

高露洁牙膏是哪个国家的品牌?高露洁牙膏哪一款最好?

高露洁是来自于美国一个比较有知名度的品牌&#xff0c;在1806年的时候创立。总部是在美国纽约公园大道&#xff0c;在1873年时&#xff0c;高露洁就已经开始销售罐装牙膏。 在1896年时期推出可折叠管牙膏&#xff0c;在口腔护理产品发展的过程中拥有着不容忽视的地位。在1992…

【Python爬虫详解】第八篇:突破反爬体系的工程实践

当矛与盾的较量进入白热化&#xff0c;突破反爬需要的不只是技巧&#xff0c;更是一套完整的工程化解决方案——本文将揭示对抗现代反爬体系的九大核心战术。 一、JavaScript混淆的深度破解 1. AST&#xff08;抽象语法树&#xff09;解混淆 案例&#xff1a;某电商平台商品价…

【Linux调整FTP端口】

Linux调整FTP端口 一、确保新端口未被占用在修改端口之前&#xff0c;可以使用以下命令检查端口是否被占用&#xff1a; 二、修改vsftpd配置文件1. 打开vsftpd配置文件2. 找到并修改端口配置3. 保存并退出4. 重启vsftpd服务 三、配置防火墙 在Linux系统中修改FTP端口&#xff0…

npm打包内存不足- JavaScript heap out of memory

直接贴出报错信息 <--- Last few GCs --->[30904:0000010F60FE58E0] 22090 ms: Scavenge 2037.4 (2069.4) -> 2036.4 (2074.2) MB, 2.5 / 0.0 ms (average mu 0.228, current mu 0.216) allocation failure [30904:0000010F60FE58E0] 22101 ms: Scavenge 2…