C++动态与静态转换区别详解

文章目录

  • 前言
  • 一、 类型检查的时机
  • 二、安全性
  • 三、适用场景
  • 四、代码示例对比
  • 总结


前言

在 C++ 中,dynamic_caststatic_cast 是两种不同的类型转换操作符,主要区别体现在类型检查的时机安全性和适用场景上。以下是它们的核心区别:


一、 类型检查的时机

  • dynamic_cast
    运行时检查。它会验证转换的合法性(比如指针或引用是否指向目标类型的有效对象)。如果转换非法,对指针返回 nullptr,对引用抛出 std::bad_cast 异常。
    要求类必须有虚函数(即多态类型),否则无法使用。

  • static_cast
    编译时检查。它信任开发者对类型安全的保证,不执行运行时检查。如果转换非法(比如无关类之间的转换),可能导致未定义行为(UB)。
    适用于编译时已知类型关系的场景。

二、安全性

  • dynamic_cast
    更安全,但需要运行时开销(RTTI)。
    主要用于多态类型的向下转型(downcast)或交叉转型(crosscast)。

  • static_cast
    不安全,但性能更高(无运行时开销)。
    需要开发者自行确保类型兼容性,否则可能导致错误。

三、适用场景

dynamic_cast 的典型用途

  • 多态类型(有虚函数的类)的向下转型:
class Base { virtual void foo() {} };
class Derived : public Base {};Base* ptr = new Derived;
Derived* derived_ptr = dynamic_cast<Derived*>(ptr); // 安全向下转型
  • 处理继承层次中的交叉转换(如多重继承中的兄弟类转换)。

static_cast 的典型用途

  • 基本类型的显式转换(如 doubleint):
double d = 3.14;
int i = static_cast<int>(d);
  • 非多态类型的指针/引用转换(需确保类型兼容):
Derived* d = new Derived;
Base* b = static_cast<Base*>(d); // 向上转型(安全,无需 dynamic_cast)
  • 显式反向转换(如 void* → int*):
void* vptr = some_address;
int* iptr = static_cast<int*>(vptr);

四、代码示例对比

向下转型(多态类型)

class Base { virtual void foo() {} }; // 必须有多态性(虚函数)
class Derived : public Base {};Base* base_ptr = new Derived;// 使用 dynamic_cast(安全,但需要虚函数)
Derived* derived_ptr1 = dynamic_cast<Derived*>(base_ptr); // 成功// 使用 static_cast(不安全,但强制转换)
Derived* derived_ptr2 = static_cast<Derived*>(base_ptr); // 可能未定义行为(若实际类型不匹配)
class Base { virtual void foo() {} };
class Derived : public Base {};Base* ptr = new Derived;
Derived* derived_ptr = dynamic_cast<Derived*>(ptr); // 安全向下转型

非多态类型转换

class A {};
class B : public A {};A* a_ptr = new B;
B* b_ptr = static_cast<B*>(a_ptr);   // 编译通过,但无运行时检查
// B* b_ptr = dynamic_cast<B*>(a_ptr); // 错误:A 不是多态类型(无虚函数)

总结

特性dynamic_caststatic_cast
类型检查时机运行时编译时
安全性高(失败返回 nullptr 或抛异常)低(依赖开发者保证)
性能有运行时开销(RTTI)无开销
适用类型多态类型(需虚函数)任意类型(包括非多态)
典型用途向下转型、交叉转型基本类型转换、显式向上/向下转型

优先选择 static_cast,除非需要处理多态类型的不确定转换(此时用 dynamic_cast)。

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

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

相关文章

探秘《矩阵之美》:解锁矩阵的无限魅力

在这个数据驱动的时代&#xff0c;矩阵作为数学中的瑰宝&#xff0c;不仅在理论研究中占据核心地位&#xff0c;更在工程技术、计算机科学、物理学、经济学等众多领域发挥着不可替代的作用。今天&#xff0c;让我们通过中科院大学耿修瑞老师&#xff08;中科院空天信息研究院研…

【MySQL】(2) 库的操作

SQL 关键字&#xff0c;大小写不敏感。 一、查询数据库 show databases; 注意加分号&#xff0c;才算一句结束。 二、创建数据库 {} 表示必选项&#xff0c;[] 表示可选项&#xff0c;| 表示任选其一。 示例&#xff1a;建议加上 if not exists 选项。 三、字符集编码和排序…

Vue3实现文件上传、下载及预览全流程详解(含完整接口调用)

文章目录 一、环境准备1.1 创建Vue3项目1.2 安装依赖1.3 配置Element Plus 二、文件上传实现2.1 基础上传组件2.2 自定义上传逻辑&#xff08;Axios实现&#xff09; 三、文件下载实现3.1 直接下载&#xff08;已知文件URL&#xff09;3.2 后端接口下载&#xff08;二进制流&am…

分布式数据存储:提升系统弹性与性能的技术之路

分布式数据存储:提升系统弹性与性能的技术之路 在当今数据爆炸式增长的时代,传统的单机存储系统已无法满足大规模、高并发、低延迟的需求。尤其是在大数据、云计算和物联网的推动下,数据存储面临着前所未有的挑战。分布式数据存储应运而生,通过将数据分布在多个物理节点上…

在编译Linux的内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整的原因

问&#xff1a;在编译Linux的内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整 答&#xff1a;在编译 Linux 内核和模块时&#xff0c;必须先编译内核镜像&#xff0c;再编译模块&#xff0c;顺序不可随意调整。 原因&#xff1a; 模块依赖内核的头文件和符…

免费使用 DeepSeek API 教程及资源汇总

免费使用 DeepSeek API 教程及资源汇总 一、DeepSeek API 资源汇总1.1 火山引擎1.2 百度千帆1.3 阿里百炼1.4 腾讯云 二、其他平台2.1 华为云2.2 硅基流动 三、总结 DeepSeek-R1 作为 2025 年初发布的推理大模型&#xff0c;凭借其卓越的逻辑推理能力和成本优势&#xff0c;迅速…

千峰React:案例二

完成对html文档还有css的引入&#xff0c;引入一下数据&#xff1a; import { func } from prop-types import ./购物车样式.css import axios from axios import { useImmer } from use-immer import { useEffect } from reactfunction Item() {return (<li classNameacti…

用DeepSeek生成批量删除处理 PDF第一页工具

安装依赖库 在运行程序之前&#xff0c;请确保安装所需的库&#xff1a; pip install pymupdf python-docx Python 程序代码 import os import fitz # PyMuPDF from docx import Documentdef delete_pdf_first_page(input_path, output_path):"""删除 PDF…

redis的下载和安装详解

一、下载redis安装包 进入redis官网查看当前稳定版本&#xff1a; https://redis.io/download/发现此时的稳定版本是6.2.4&#xff0c; 此时可以去这个网站下载6.2.4稳定版本的tar包。 暂时不考虑不在windows上使用redis&#xff0c;那样将无法发挥redis的性能 二、上传tar…

如何使用 Jenkins 实现 CI/CD 流水线:从零开始搭建自动化部署流程

如何使用 Jenkins 实现 CI/CD 流水线:从零开始搭建自动化部署流程 在软件开发过程中,持续集成(CI)和持续交付(CD)已经成为现代开发和运维的标准实践。随着代码的迭代越来越频繁,传统的手动部署方式不仅低效,而且容易出错。为了提高开发效率和代码质量,Jenkins作为一款…

Python基于Django的网络课程在线学习平台【附源码】

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

Pytorch为什么 nn.CrossEntropyLoss = LogSoftmax + nn.NLLLoss?

为什么 nn.CrossEntropyLoss LogSoftmax nn.NLLLoss&#xff1f; 在使用 PyTorch 时&#xff0c;我们经常听说 nn.CrossEntropyLoss 是 LogSoftmax 和 nn.NLLLoss 的组合。这句话听起来简单&#xff0c;但背后到底是怎么回事&#xff1f;为什么这两个分开的功能加起来就等于…

rabbitmq 延时队列

要使用 RabbitMQ Delayed Message Plugin 实现延时队列&#xff0c;首先需要确保插件已安装并启用。以下是实现延时队列的步骤和代码示例。 1. 安装 RabbitMQ Delayed Message Plugin 首先&#xff0c;确保你的 RabbitMQ 安装了 rabbitmq-delayed-message-exchange 插件。你可…

在 Vue 单文件组件(SFC)中,标签的显式关闭与隐式关闭有着重要的区别

一、显式关闭标签 1、定义&#xff1a; 所有的 HTML 标签都必须有一个对应的结束标签。 自闭合标签也必须使用 / 来关闭。 <template> <div> <p>这是一个段落</p> <img src"image.png"…

第四届大数据、区块链与经济管理国际学术会议

重要信息 官网&#xff1a;www.icbbem.com 时间&#xff1a;2025年3月14-16日 地点&#xff1a;中国-武汉 &#xff08;线上召开&#xff09; 简介 第四届大数据、区块链与经济管理国际学术会议(ICBBEM 2025)&#xff0c;将于2025年3月14-16日在中国湖北省武汉市召开。…

每日十个计算机专有名词 (7)

Metasploit 词源&#xff1a;Meta&#xff08;超越&#xff0c;超出&#xff09; exploit&#xff08;漏洞利用&#xff09; Metasploit 是一个安全测试框架&#xff0c;用来帮助安全专家&#xff08;也叫渗透测试人员&#xff09;发现和利用计算机系统中的漏洞。你可以把它想…

使用Docker Compose部署 MySQL8

MySQL 8 是一个功能强大的关系型数据库管理系统,而 Docker 则是一个流行的容器化平台。结合使用它们可以极大地简化 MySQL 8 的部署过程,并且确保开发环境和生产环境的一致性。 安装 Docker 和 Docker Compose 首先,确保你的机器上已经安装了 Docker 和 Docker Compose。 …

mamba_ssm和causal-conv1d详细安装教程

1.前言 Mamba是近年来在深度学习领域出现的一种新型结构&#xff0c;特别是在处理长序列数据方面表现优异。在本文中&#xff0c;我将介绍如何在 Linux 系统上安装并配置 mamba_ssm 虚拟环境。由于官方指定mamba_ssm适用于 PyTorch 版本高于 1.12 且 CUDA 版本大于 11.6 的环境…

c++中初始化列表的使用

在 C 中&#xff0c;初始化列表是在构造函数的定义中&#xff0c;用于对类的成员变量进行初始化的一种方式。它紧跟在构造函数的参数列表之后&#xff0c;使用冒号 : 分隔&#xff0c;各成员变量的初始化用逗号 , 分隔。下面详细介绍初始化列表及其参数的含义。 基本语法 clas…

《Linux系统编程篇》System V信号量实现生产者与消费者问题(Linux 进程间通信(IPC))——基础篇(拓展思维)

文章目录 &#x1f4da; **生产者-消费者问题**&#x1f511; **问题分析**&#x1f6e0;️ **详细实现&#xff1a;生产者-消费者****步骤 1&#xff1a;定义信号量和缓冲区****步骤 2&#xff1a;创建信号量****步骤 3&#xff1a;生产者进程****步骤 4&#xff1a;消费者进程…