【c++】四种类型转换形式
【c++】四种类型转换形式
编译时:
static_cast(静态转换)
const_cast(去常性转换)
reinterpret_cast(重新解释转换,直接转换地址)
运行时:
dynamic_cast(动态转换,运行时类型识别 RTTI)
static_cast(静态转换)
| 用途 | 描述 | 注意事项 |
|---|---|---|
| 基本数据类型之间的转换 | 用于 int 转 double、char 转 int 等类型之间的转换。 | 适用于已知类型的转换,比 C 风格转换更安全。 |
void* 转换为其他类型 | 用于将 void* 指针还原为具体类型的指针。 | 必须确保指针类型正确,避免未定义行为。 |
| 左值转换为右值 | 用于将左值转换为右值引用,常用于移动语义。 | 强制转换为右值引用,触发移动构造。 |
| 类型层次结构中的指针和引用转换 | 在类继承关系中,用于基类和派生类之间的转换。 | 只能进行安全的向上转换,向下转换需要 dynamic_cast。 |
int 类型转换为枚举 | 允许 int 与枚举类型之间的转换。 | 适用于整数到枚举的安全转换。 |
static_cast 在模板中的应用 | 用于确保目标类型和原始类型一致,并在模板编程中进行类型转换。 | 使用 static_assert 进行编译期类型检查。 |
1. 基本数据类型转换
static_cast 可用于基本数据类型之间的转换,如 int 转 double、char 转 int,等价于 C 风格转换,但更安全。
#include <iostream>int main() {double d = 3.14159;int i = static_cast<int>(d); // 截断小数部分,转换为 3char c = 'A';int ascii = static_cast<int>(c); // 将字符 'A' 转换为 ASCII 码std::cout << "i = " << i << ", ascii = " << ascii << std::endl;return 0;
}
✅ 优点:比 C 风格转换更安全,可读性更好,避免了 reinterpret_cast 的风险。
2. void* 转换为其他类型
static_cast 可以用于将 void* 还原为具体类型,但必须确保指针类型正确,否则可能导致未定义行为。
#include <iostream>int main() {int a = 42;void* pVoid = &a; // int* → void*int* pInt = static_cast<int*>(pVoid); // void* → int*std::cout << "pInt = " << *pInt << std::endl;return 0;
}
✅ 适用于已知原始类型的情况,如果不确定类型,应使用 reinterpret_cast。
3. 左值转换为右值
在 C++11 及更高版本中,static_cast 可以将左值转换为右值引用,用于移动语义。
#include <iostream>
#include <utility> // std::moveclass Data {
public:Data() { std::cout << "构造函数\n"; }Data(const Data&) { std::cout << "拷贝构造\n"; }Data(Data&&) { std::cout << "移动构造\n"; }
};int main() {Data d;Data d2 = static_cast<Data&&>(d); // 强制转换为右值引用,触发移动构造return 0;
}
✅ 与 std::move 类似,但 static_cast<Data&&> 是显式的转换方式。
4. 类型层次结构中的指针和引用转换
在类的继承关系中,static_cast 可以在基类和派生类之间进行转换,但仅限安全的向上转换。
#include <iostream>class Base {
public:virtual void show() { std::cout << "Base 类\n"; }
};class Derived : public Base {
public:void show() override { std::cout << "Derived 类\n"; }
};int main() {Derived d;Base* pBase = static_cast<Base*>(&d); // 向上转换pBase->show(); // 仍然调用 Derived 的 `show()`return 0;
}
⚠️ 向下转换(Base* → Derived*)是不安全的,需要用 dynamic_cast。
5. int 类型转换为枚举
static_cast 允许整数和枚举类型之间的转换。
#include <iostream>enum Color { RED, GREEN, BLUE };int main() {int num = 1;Color c = static_cast<Color>(num); // 将 int 转换为枚举类型std::cout << "c = " << c << std::endl;return 0;
}
✅ 适用于整数到枚举的安全转换。
6. static_cast 在模板中的应用
在模板编程中,可以使用 static_cast 确保目标类型和原始类型一致。
#include <iostream>
#include <type_traits>template <typename T, typename U>
T convert(U value) {static_assert(std::is_convertible<U, T>::value, "类型不兼容!");return static_cast<T>(value);
}int main() {double d = 3.14;int i = convert<int>(d); // double → intstd::cout << "i = " << i << std::endl;return 0;
}
✅ static_assert 可用于编译期检查类型是否可以转换。
const_cast(去常性转换)
| 特点 | 描述 |
|---|---|
| 只能对同类型使用 | const_cast 类型必须相同。 |
| 不能用于基本数据类型 | 不能用于基本数据类型之间的转换(例如:int → double)。 |
| 转换目标为指针或引用 | 只能将指针或引用的常量属性去除,而不能作用于值类型。 |
常量指针/引用被转换为非常量的指针/引用,并仍然指向原来的对象
例子:
-
常量指针转为非常量指针
#include <iostream>void modifyValue(const int* ptr) {// const_cast 去常性转换int* modifiablePtr = const_cast<int*>(ptr);*modifiablePtr = 20; // 可以修改原对象 }int main() {const int a = 10;modifyValue(&a); // 将常量指针转换为非常量指针return 0; } -
常量引用转为非常量引用
#include <iostream>void modifyValue(const int& ref) {// const_cast 去常性转换int& modifiableRef = const_cast<int&>(ref);modifiableRef = 20; // 可以修改原对象 }int main() {const int a = 10;modifyValue(a); // 将常量引用转换为非常量引用return 0; }
注意事项:
const_cast只会移除常量属性,并不会改变对象本身。- 对于常量对象的修改仍然是未定义行为,因此不应使用
const_cast去修改那些原本是常量的数据。
reinterpret_cast(重新解释转换)
是 C++ 中最危险的类型转换之一,它将数据从一种类型“强制”转换为另一种类型,并且不进行任何类型检查。
它是按位解释的
| 特点 | 描述 |
|---|---|
| 最危险的转换 | reinterpret_cast 不进行任何类型检查,可能导致未定义行为。 |
| 按位解释 | 转换直接基于内存的二进制表示,不考虑类型的语义。 |
| 指针之间的转换 | 可用于不同类型的指针之间的转换。 |
| 指针与整数之间的转换 | 可将指针转换为整数,反之亦然。 |
1. 指针类型转换
#include <iostream>int main() {int a = 42;// 强制将 int* 转换为 double*,危险操作,按位解释double* p = reinterpret_cast<double*>(&a);std::cout << *p << std::endl; // 不确定行为,可能崩溃return 0;
}
2. 指针与整数转换
#include <iostream>int main() {int* p = reinterpret_cast<int*>(0x1234); // 将整数转换为指针std::cout << "Pointer: " << p << std::endl;uintptr_t addr = reinterpret_cast<uintptr_t>(p); // 将指针转换为整数std::cout << "Address as integer: " << addr << std::endl;return 0;
}
动态转换(dynamic_cast)
是一种用于在类层次结构中进行指针或引用类型转换的操作,特别适用于下行转换(基类指针或引用转换为派生类指针或引用)。dynamic_cast 在运行时检查类型安全,依赖于虚函数表和运行时类型信息(RTTI),通过虚函数表中的信息来实现类型检查。
动态转换的基本概念:
-
上行转换(向上转换):
- 向上转换是指派生类对象转换为基类指针或引用是在编译时进行的,与静态类型转换等价,不查虚表
-
下行转换(向下转换):
- 向下转换是指基类指针或引用转换为派生类指针或引用。这种转换在运行时需要类型检查,
- 并且只有在公有继承和继承关系中存在虚函数时才有效,否则没有运行时类型信息(RTTI)进行类型检查。
- 使用
dynamic_cast来进行下行转换时,转换成功时返回派生类指针或引用,转换失败时返回nullptr(对于指针类型),或者抛出std::bad_cast异常(对于引用类型)。 - 例如:
class Base { public:virtual ~Base() {} // 必须有虚析构函数,以支持RTTI };class Derived : public Base {};int main() {Base* pBase = new Derived();Derived* pDerived = dynamic_cast<Derived*>(pBase); // 成功,转换为派生类指针if (pDerived) {std::cout << "转换成功!" << std::endl;} else {std::cout << "转换失败!" << std::endl;}delete pBase;return 0; }- 如果
pBase实际上指向一个Derived类型对象,则pDerived会成功转换,并指向该对象。 - 如果
pBase并不指向Derived类型对象,dynamic_cast将返回nullptr,指示转换失败。
- 如果
如何判断是否能够进行下行转换:
- 条件:只有当类之间存在虚函数(如虚析构函数)时,RTTI 才会被启用,
dynamic_cast才能进行类型检查。 - 执行流程:
dynamic_cast会查询对象的虚函数表(vtable)。- 如果查询到类型匹配,则转换成功。
- 如果查询失败,则返回
nullptr(对于指针类型),或抛出异常std::bad_cast(对于引用类型)。
相关文章:
【c++】四种类型转换形式
【c】四种类型转换形式 编译时: static_cast(静态转换) const_cast(去常性转换) reinterpret_cast(重新解释转换,直接转换地址) 运行时: dynamic_cast(动态转换,运行时类…...
Unity 制作2D动画必要准备:启动篇
制作Unity 2D动画需要准备以下内容: 美术素材准备 选择或绘制符合需求的2D精灵图(如像素风格角色、场景元素)确保素材包含完整动画序列帧(如行走/攻击/跳跃等动作分解)注意素材尺寸统一性,建议采用网格化排…...
半小时在本地部署DeepSeek的Janus Pro,进行图片分析和文生图
半小时在本地部署DeepSeek的Janus Pro,进行图片分析和文生图 下载Janus Pro源代码下载模型文件创建Python虚拟环境安装依赖包Janus Pro测试运行程序图片分析测试文生图测试使用中文提示词使用英文提示词 测试印象: 整体模型体积较小,个人可以…...
急停信号的含义
前言: 大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在开发C#的运动控制程序的时候,一个必要的步骤就是确认设备按钮的急停…...
设置mysql的主从复制模式
mysql设置主从复制模式似乎很容易,关键在于1)主库启用二进制日志,2)从库将主库设为主库。另外,主从复制,复制些什么?从我现在获得的还很少的经验来看,复制的内容有表,用户…...
三角拓扑聚合优化器TTAO-Transformer-BiLSTM多变量回归预测(Maltab)
三角拓扑聚合优化器TTAO-Transformer-BiLSTM多变量回归预测(Maltab) 完整代码私信回复三角拓扑聚合优化器TTAO-Transformer-BiLSTM多变量回归预测(Maltab) 一、引言 1、研究背景和意义 在现代数据科学领域,时间序列…...
东方财富Android面试题及参考答案
接口和抽象类的区别是什么? 定义与语法 接口:接口是一种抽象类型,它只包含方法签名、常量定义,方法默认是public、abstract的,常量默认是public、static、final的。接口不能包含实例变量和普通方法的实现。抽象类:抽象类是一种不能被实例化的类,它可以包含抽象方法和具体…...
ArcGIS基础知识之ArcMap基础设置——ArcMap选项:常规选项卡设置及作用
作为一名 GIS 从业者,ArcMap 是我们日常工作中不可或缺的工具。对于初学者来说,掌握 ArcMap 的基础设置是迈向 GIS 分析与制图的第一步。今天,就让我们一起深入了解 ArcMap 选项中常规选项卡的各个设置,帮助大家更好地使用这款强大的软件。 在 ArcMap 中,常规选项卡是用户…...
element-ui时间组件同一个月内选择/30天内选择
element-ui时间组件同一个月内选择/30天内选择 同一个月 <el-date-picker v-model"time" type"datetimerange"range-separator"至" start-placeholder"开始时间"value-format"timestamp" :picker-options"pickerO…...
Linux Media 子系统 V4l2
一 创建 V4l2 的 entity 在Linux内核的Media Controller框架中,V4L2设备作为实体(entity)的注册过程涉及以下步骤: 1. 初始化Media Controller结构 驱动首先创建一个media_device实例,并与V4L2设备(如v4…...
14,.左下角的值,路径和,由序列确定树
找树左下角的值 迭代法 层序遍历 class Solution { public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> qu;qu.push(root);TreeNode* leftqu.front();while(!qu.empty()){int szqu.size();leftqu.front();for(int i0;i<sz;i){TreeNode* curqu.fron…...
RabbitMQ 如何设置限流?
RabbitMQ 的限流(流量控制)主要依赖于 QoS(Quality of Service) 机制,即 prefetch count 参数。这个参数控制每个消费者一次最多能获取多少条未确认的消息,从而避免某个消费者被大量消息压垮。 1. RabbitMQ…...
Python常见面试题的详解3
1. 类和对象的区别、对象访问类的方法、创建对象时的操作 类和对象的区别:类是一种抽象的概念,它定义了一组具有相同属性和方法的对象的蓝图或模板。而对象是类的具体实例,是根据类创建出来的实体,每个对象都有自己独立的状态&am…...
【推理llm论文精读】DeepSeek V3技术论文_精工见效果
先附上原始论文和效果对比https://arxiv.org/pdf/2412.19437 摘要 (Abstract) DeepSeek-V3是DeepSeek-AI团队推出的最新力作,一个强大的混合专家(Mixture-of-Experts,MoE)语言模型。它拥有671B的总参数量,但每个tok…...
python自动化测试之Pytest框架之YAML详解以及Parametrize数据驱动!
一、YAML详解 YAML是一种数据类型,它能够和JSON数据相互转化,它本身也是有很多数据类型可以满足我们接口 的参数类型,扩展名可以是.yml或.yaml 作用: 1.全局配置文件 基础路径,数据库信息,账号信息&…...
DeepSeek 本地部署指南
在人工智能飞速发展的今天,大语言模型的应用越来越广泛。DeepSeek 作为一款强大的大语言模型,具备出色的语言理解和生成能力。然而,许多用户希望能够在本地部署 DeepSeek,以实现更高的隐私性、更低的延迟和更好的定制化。本文将为…...
[LeetCode]day21 15.三数之和
题目链接 题目描述 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复…...
Unity学习part1
课程为b站【Unity教程】零基础带你从小白到超神 1、脚本执行顺序 unity的脚本执行顺序不像blender的修改器那样按顺序执行,而是系统默认给配置一个值,值越小,执行顺序越靠前(注意,这个顺序是全局生效的) …...
【AI知识点】Adversarial Validation(对抗验证)
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】【AI应用】 Adversarial Validation(对抗验证) 是一种用于检查 训练集(Train Set)和测试集(Test Set)是否同分布 的方法。它…...
力扣 15.三数之和
题目: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的…...
Spring boot中实现字典管理
数据库脚本 CREATE TABLE data_dict (id bigint NOT NULL COMMENT 主键,dict_code varchar(32) DEFAULT NULL COMMENT 字典编码,dict_name varchar(64) DEFAULT NULL COMMENT 字典名称,dict_description varchar(255) DEFAULT NULL COMMENT 字典描述,dict_status tinyint DEFA…...
唯一值校验的实现思路(续)
本文接着上一篇文章《唯一值校验的实现思路》,在后端实现唯一值校验。用代码实现。 /*** checkUniqueException[唯一值校验]** param entity 新增或编辑的学生实体* param insert 是否新增,如果是传入true;反之传入false* return void* date…...
【AI论文】10亿参数大语言模型能超越405亿参数大语言模型吗?重新思考测试时计算最优缩放
摘要:测试时缩放(Test-Time Scaling,TTS)是一种通过在推理阶段使用额外计算来提高大语言模型(LLMs)性能的重要方法。然而,目前的研究并未系统地分析策略模型、过程奖励模型(Process …...
Ubuntu20.04上搭建nginx正向代理提供上网服务
背景:公司很多电脑因软件管控问题不得不禁止设备上网,现需搭建上网代理服务器提供给这些用户使用。 操作系统:ubuntu20.04 工具:nginx-1.25.4 1、下载nginx安装包及依赖 由于nginx默认只持支持转发http协议,所以如…...
web前端布局--使用element中的Container布局容器
前端页面,跟Qt中一样,都是有布局设置的。 先布局,然后再在各布局中添加显示的内容。 Element网站布局容器:https://element.eleme.cn/#/zh-CN/componet/container 1.将element相应的布局容器代码layout,粘贴到vue项…...
使用 PDF SDK 通过页面分割和数据提取对建筑图纸进行分类
一家专门从事设计和建设的建筑公司对大量多页建筑 PDF 图纸进行分类,从而提高协作和运营效率。 这类公司通常承担多个建筑设计项目,每个项目包含多个设计图纸,如详细的结构计划、电气与水管计划、机械计划等。如果项目图纸可以在上传后自动分…...
Linux命名管道与共享内存
命名管道与共享内存 命名管道介绍和基本使用 理解了匿名管道后,命名管道的理解就会变得容易。在前面使用匿名管道时可以发现,之所以可以匿名是因为由父进程创建,子进程拷贝所以子进程和父进程都可以看到这个管道。但是如果对于任意两个进程…...
maven web项目如何定义filter
在 Maven Web 项目中定义一个 Servlet 过滤器(Filter),需要遵循 Java Servlet 规范,并利用 Maven 来管理项目结构和依赖。下面是如何在 Maven Web 项目中定义和配置一个过滤器的基本步骤: 1. 创建过滤器类 首先&…...
使用 Notepad++ 编辑显示 MarkDown
Notepad 是一款免费的开源文本编辑器,专为 Windows 用户设计。它是替代记事本(Notepad)的最佳选择之一,因为它功能强大且轻量级。Notepad 支持多种编程语言和文件格式,并可以通过插件扩展其功能。 Notepad 是一款功能…...
@synchronized的使用
synchronized 介绍 synchronized 是 Objective-C 提供的一种 互斥锁(Mutex),它用于确保一段代码在同一时间只有一个线程能执行,避免多线程访问共享资源时出现数据竞争。 基本语法 synchronized (lockObject) {// 需要加锁的代码…...
