当前位置: 首页 > news >正文

dynamic_cast和static_cast和const_cast

dynamic_cast 在 C++ 中的作用

dynamic_cast 是 C++ 运行时类型转换(RTTI, Run-Time Type Identification)的一部分,主要用于:

  • 安全的多态类型转换
  • 检查类型的有效性
  • 向下转换(Downcasting)
  • 跨类层次的指针或引用转换

它只能用于 带有虚函数的类,否则 dynamic_cast 将无法工作。


1. dynamic_cast 的作用

1.1 向下转换(Downcasting)

用于将 基类(Base Class)指针/引用 转换为 派生类(Derived Class)指针/引用,并在运行时 检查类型安全性

示例:

#include <iostream>
using namespace std;class Base {
public:virtual void show() { cout << "Base class\n"; } // 需要虚函数
};class Derived : public Base {
public:void show() override { cout << "Derived class\n"; }
};int main() {Base* basePtr = new Derived(); // 基类指针指向派生类对象// 使用 dynamic_cast 进行向下转换Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);if (derivedPtr) {derivedPtr->show(); // ✅ 成功转换并调用 Derived::show()} else {cout << "Conversion failed\n";}delete basePtr;return 0;
}

输出:

Derived class

dynamic_cast 成功转换,因为 basePtr 实际指向的是 Derived 对象。


1.2 失败情况

如果 basePtr 实际上指向的是 Base 类型的对象,而不是 Derived,那么转换会失败,返回 nullptr(对于指针)。

Base* basePtr = new Base();
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);if (derivedPtr) {derivedPtr->show();
} else {cout << "Conversion failed\n"; // ✅ 这里转换失败
}

输出:

Conversion failed

2. dynamic_cast 适用于引用

dynamic_cast 也可以用于 引用转换,但如果转换失败,会抛出 std::bad_cast 异常。

#include <iostream>
#include <typeinfo>
using namespace std;class Base { public: virtual ~Base() {} };
class Derived : public Base {};int main() {Base baseObj;try {Derived& derivedRef = dynamic_cast<Derived&>(baseObj); // ❌ 失败,抛出异常} catch (const std::bad_cast& e) {cout << "Exception: " << e.what() << endl;}return 0;
}

输出:

Exception: std::bad_cast

✅ 由于 baseObj 不是 Derived 类型,dynamic_cast 失败并抛出 std::bad_cast 异常。


3. dynamic_caststatic_cast 的区别

比较项dynamic_caststatic_cast
转换类型仅限于 带虚函数的多态类任何相关类型
运行时检查有类型检查(RTTI)无类型检查
失败情况指针返回 nullptr,引用抛出 std::bad_cast可能导致 未定义行为
转换方向只能用于向下转换向上、向下转换均可
性能运行时开销较大(涉及 RTTI 查询)编译时转换,无额外开销

示例:static_cast vs dynamic_cast

Base* basePtr = new Base();// static_cast(不会进行检查,可能导致未定义行为)
Derived* derivedPtr1 = static_cast<Derived*>(basePtr); // ❌ 可能出现未定义行为
derivedPtr1->show(); // 可能崩溃// dynamic_cast(安全,但可能返回 nullptr)
Derived* derivedPtr2 = dynamic_cast<Derived*>(basePtr); // ✅ 失败时返回 nullptr
if (derivedPtr2) derivedPtr2->show();

总结

  • dynamic_cast 安全但慢,适合 不确定基类指针实际指向的对象类型 时。
  • static_cast 快但危险,仅适合 明确知道转换是安全的情况下

4. 什么时候使用 dynamic_cast

使用 dynamic_cast 的最佳场景

  1. 向下转换(基类指针/引用 → 派生类指针/引用)。
  2. 运行时类型检查(避免 static_cast 可能的未定义行为)。
  3. 接口类(如 Base* ptr 指向某个不确定类型的派生类,需要判断其类型)。

避免 dynamic_cast 的情况

  1. 不涉及多态(没有 virtual 函数,dynamic_cast 无法工作)。
  2. 已知类型安全的转换(可用 static_cast 代替)。
  3. 高性能场景dynamic_cast 有运行时开销)。

5. dynamic_cast 在实际应用中的示例

5.1 多态事件处理

class Event { public: virtual ~Event() {} };
class MouseEvent : public Event { public: void click() { cout << "Mouse clicked\n"; } };
class KeyboardEvent : public Event { public: void press() { cout << "Key pressed\n"; } };void handleEvent(Event* event) {if (MouseEvent* mouse = dynamic_cast<MouseEvent*>(event)) {mouse->click();} else if (KeyboardEvent* key = dynamic_cast<KeyboardEvent*>(event)) {key->press();} else {cout << "Unknown event\n";}
}int main() {MouseEvent mouse;KeyboardEvent keyboard;handleEvent(&mouse);    // ✅ 输出 "Mouse clicked"handleEvent(&keyboard); // ✅ 输出 "Key pressed"return 0;
}

dynamic_cast 允许在运行时确定事件的类型,并调用相应的处理逻辑。


const_cast 在 C++ 中的作用

const_cast 是 C++ 提供的 四种类型转换运算符static_castdynamic_castconst_castreinterpret_cast)之一,专门用于去掉或添加 const / volatile 限定符

它允许:

  • 移除 const 限定符(常见用途)
  • 移除 volatile 限定符
  • 添加 const(几乎没用)

1. const_cast 的基本用法

1.1 去掉 const 修饰符

通常,const_cast 用于将 const 指针转换为非 const 指针,从而允许修改 const 变量(⚠️ 仅适用于非常量对象)。

示例:

#include <iostream>
using namespace std;void modifyConstValue(const int* ptr) {int* modifiablePtr = const_cast<int*>(ptr); // 去掉 const 限定符*modifiablePtr = 42; // 现在可以修改它
}int main() {int x = 10;modifyConstValue(&x);cout << "x = " << x << endl; // ✅ 输出 x = 42return 0;
}

输出:

x = 42

const_cast<int*> 移除了 ptrconst 限定符,使得 modifiablePtr 可以修改 x


2. const_cast 使用的注意事项

2.1 const_cast 不能修改真正的 const 变量

如果你试图修改一个 真正的 const 变量,行为是 未定义的(UB, Undefined Behavior)

示例(错误):

const int y = 100;
int* ptr = const_cast<int*>(&y);
*ptr = 200; // ❌ 未定义行为
cout << "y = " << y << endl;

⚠️ 即使编译通过,运行结果可能是:

y = 100  // ❌ 修改失败(某些编译器可能优化 `y` 为常量)

y = 200  // ❌ 可能错误修改(取决于编译器)

为什么?

  • const int y = 100; 可能会被编译器优化到只读存储区,因此试图修改它可能导致 程序崩溃无效修改

正确的使用方式:
const_cast 只能用于去掉 const 修饰符的指针/引用,而不能用于真正的 const 变量


3. const_cast 用于函数参数

3.1 const_cast 解除 const 限定

有时,我们在 只接受非 const 参数的旧 C 库 中,需要传递 const 变量,这时 const_cast 可以解决问题。

#include <iostream>
using namespace std;void legacyFunction(char* str) { // 旧 C 库接口,必须接收非 conststr[0] = 'H'; // 修改字符串
}void wrapperFunction(const char* str) {legacyFunction(const_cast<char*>(str)); // 去掉 const
}int main() {char text[] = "hello";wrapperFunction(text);cout << text << endl; // ✅ 输出 "Hello"return 0;
}

const_cast<char*> 允许 legacyFunction() 修改字符串。


4. const_cast 用于成员函数

在 C++ 类中,const_cast 可用于 const 成员函数中修改成员变量

4.1 修改 mutable 变量

如果某个成员变量在 const 方法中需要修改,推荐使用 mutable,而不是 const_cast

class Example {
private:mutable int counter = 0;
public:void increaseCounter() const {counter++; // ✅ 因为 counter 是 mutable,可以在 const 方法中修改}
};

mutable 是更好的选择!

4.2 const_castconst 方法中修改成员变量

如果不能使用 mutable,可以用 const_cast 强行去掉 const

class Example {
private:int counter = 0;
public:void modify() const {const_cast<Example*>(this)->counter = 100; // 去掉 const 限定符}
};

⚠️ 注意:这会破坏 const 语义,最好避免!


5. const_cast 与其他类型转换的区别

转换方式用途
const_cast仅用于 去掉或添加 const/volatile
static_cast编译时转换,用于普通类型转换
dynamic_cast运行时类型转换,用于 多态类
reinterpret_cast低级别强制转换,用于不同类型的二进制转换

6. 什么时候应该使用 const_cast

适用场景

  1. 调用旧 C 库时,避免 const 兼容性问题(如 const char*char*)。
  2. const 成员函数中修改成员变量(但推荐 mutable)。
  3. 特定场景下移除 const 以提高灵活性(如优化某些代码)。

不推荐使用的情况

  1. 试图修改真正的 const 变量(未定义行为)。
  2. 滥用 const_cast 破坏 const 语义(影响代码可读性)。
  3. 可以使用 mutable 代替的情况

7. const_cast 适用的真实案例

案例:日志系统

log() 方法中,可能希望const 对象中增加日志计数

class Logger {
private:mutable int log_count = 0;
public:void log(const string& msg) const {cout << "Log: " << msg << endl;const_cast<Logger*>(this)->log_count++; // ✅ 修改 log_count}
};

✅ 这里使用 mutable 更合适,但 const_cast 也是可选方案。


8. 总结

const_cast 的作用

  • 去掉 const 限定符,使 const 指针/引用可以修改数据
  • 允许 const 方法修改成员变量(但推荐 mutable)。
  • 用于传递 const 数据给不兼容 const 的旧 C 代码

⚠️ const_cast 的注意事项

  • 不能修改真正的 const 变量,否则是 未定义行为(UB)
  • 滥用会破坏 const 语义,影响代码可读性。
  • 如果可能,使用 mutable 代替 const_cast

🚀 最佳实践

  1. 如果可能,避免 const_cast,使用 mutable 或者 static_cast
  2. 只有在调用 C 代码或 const 兼容性问题时使用 const_cast
  3. 确保 const_cast 仅用于非 const 变量,否则可能导致 UB(未定义行为)

何时使用?

  • ✅ 需要 安全的向下转换(从 Base*Derived*)。
  • ✅ 处理 运行时不确定的多态对象(如 GUI 事件、游戏对象)。
  • 已知类型的转换 应该使用 static_cast 以提高性能。

结论

  • dynamic_cast 适用于多态类型转换,尤其是 向下转换
  • 运行时类型检查(RTTI)确保转换安全,但性能较 static_cast 略低
  • 适用于事件处理、插件系统等场景,但不建议在高性能代码中滥用。

相关文章:

dynamic_cast和static_cast和const_cast

dynamic_cast 在 C 中的作用 dynamic_cast 是 C 运行时类型转换&#xff08;RTTI, Run-Time Type Identification&#xff09;的一部分&#xff0c;主要用于&#xff1a; 安全的多态类型转换检查类型的有效性向下转换&#xff08;Downcasting&#xff09;跨类层次的指针或引用…...

DEEPSEEK与GPT等AI技术在机床数据采集与数字化转型中的应用与影响

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;深度学习、自然语言处理等先进技术开始广泛应用于各行各业。在制造业尤其是机床行业&#xff0c;AI技术的融合带来了巨大的变革&#xff0c;尤其在机床数据采集与机床数字化方面的应用。本文将探讨DEEPSEEK、…...

高速存储文章目录

《zynq tcp万兆网和ftp协议分析-CSDN博客》 《国产fpga nvme ip高速存储方案设计_fpga 高速存储-CSDN博客》 《国微pcie switch 8748高速存储方案设计_国产pcie switch-CSDN博客》 《FPGA SATA高速存储设计-CSDN博客》 《FPGA NVME高速存储设计_690t fpga-CSDN博客》 《zy…...

车载测试工具 --- CANoe VH6501 进行Not Acknowledge (NAck) 测试

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…...

【清晰教程】通过Docker为本地DeepSeek-r1部署WebUI界面

【清晰教程】本地部署DeepSeek-r1模型-CSDN博客 目录 安装Docker 配置&检查 Open WebUI 部署Open WebUI 安装Docker 完成本地DeepSeek-r1的部署后【清晰教程】本地部署DeepSeek-r1模型-CSDN博客&#xff0c;通过Docker为本地DeepSeek-r1部署WebUI界面。 访问Docker官…...

Linux运维——用户管理

Linux用户管理 一、Linux用户管理要点二、常用命令2.1、groupadd2.2、groupdel2.3、groupmod2.4、groups2.5、useradd2.6、userdel2.7、passwd2.9、su2.10、sudo2.10.1、给普通用户授权 sudo2.10.2、 免密码授权 sudo 一、Linux用户管理要点 创建用户组 - 使用 groupadd删除用…...

mac下dify+deepseek部署,实现私人知识库

目前deepseek 十分火爆&#xff0c;本地部署实现私有知识库&#xff0c;帮助自己日常工作&#xff0c;上一篇使用工具cherry studio可以做到私人知识库。今天学习了一下&#xff0c;使用Dify链接deepseek&#xff0c;实现私人知识库&#xff0c;也非常不错&#xff0c;这里分享…...

Linux中设置开机运行指令

系统&#xff1a;Debian 12 使用systemd来设置开机自启动脚本或命令是一个更加现代且推荐的方法。下面是具体的步骤&#xff1a; 创建守护脚本 首先&#xff0c;你需要创建一个Shell脚本文件&#xff0c;比如mydaemon.sh&#xff0c;并在其中编写你的守护脚本逻辑。确保这个脚…...

IDEA中列举的是否是SpringBoot的依赖项的全部?在哪里能查到所有依赖项,如何开发自己的依赖项让别人使用

在 IntelliJ IDEA 中列举的依赖项并不一定是 Spring Boot 项目的全部依赖项。IDEA 通常只显示你在 pom.xml&#xff08;Maven&#xff09;或 build.gradle&#xff08;Gradle&#xff09;中显式声明的依赖项&#xff0c;而这些依赖项本身可能还会引入其他传递性依赖。 1. 如何…...

Ollama命令使用指南

Ollama 命令使用指南 Ollama 命令使用指南1. Ollama 命令概览2. Ollama 命令详解2.1 启动 Ollama2.2 创建模型2.3 查看模型信息2.4 运行模型2.5 停止运行的模型2.6 从注册表拉取模型2.7 推送模型到注册表2.8 列出本地模型2.9 查看正在运行的模型2.10 复制模型2.11 删除模型 3. …...

LIMO:上海交大的工作 “少即是多” LLM 推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型&#xff08;LLM&#xff09;中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据&#xff08;通常超过 100,000 个示例&#xff09;&#xff0c;但本文展…...

Android studio怎么创建assets目录

在Android Studio中创建assets文件夹是一个简单的步骤&#xff0c;通常用于存储不需要编译的资源文件&#xff0c;如文本文件、图片、音频等 main文件夹&#xff0c;邮件new->folder-assets folder...

常见的前端框架和库有哪些

1. React 描述&#xff1a;由 Facebook 开发的一个 JavaScript 库&#xff0c;用于构建用户界面&#xff0c;尤其是单页面应用&#xff08;SPA&#xff09;。特点&#xff1a; 基于组件的架构&#xff0c;便于重用 UI 组件。使用虚拟 DOM 提升性能。容易与其他库和框架集成。 …...

【批量获取图片信息】批量获取图片尺寸、海拔、分辨率、GPS经纬度、面积、位深度、等图片属性里的详细信息,提取出来后导出表格,基于WPF的详细解决方案

摄影工作室通常会有大量的图片素材&#xff0c;在进行图片整理和分类时&#xff0c;需要知道每张图片的尺寸、分辨率、GPS 经纬度&#xff08;如果拍摄时记录了&#xff09;等信息&#xff0c;以便更好地管理图片资源&#xff0c;比如根据图片尺寸和分辨率决定哪些图片适合用于…...

数据结构与算法(test3)

七、查找 1. 看图填空 查找表是由同一类型的数据元素&#xff08;或记录&#xff09;构成的集合。例如上图就是一个查找表。 期中&#xff08;1&#xff09;是______________. (2)是______________(3)是_____关键字_______。 2. 查找(Searching) 就是根据给定的某个值, 在查…...

基于Python的人工智能驱动基因组变异算法:设计与应用(下)

3.3.2 数据清洗与预处理 在基因组变异分析中,原始数据往往包含各种噪声和不完整信息,数据清洗与预处理是确保分析结果准确性和可靠性的关键步骤。通过 Python 的相关库和工具,可以有效地去除噪声、填补缺失值、标准化数据等,为后续的分析提供高质量的数据基础。 在基因组…...

C++ 顺序表

顺序表的操作有以下&#xff1a; 1 顺序表的元素插入 给定一个索引和元素&#xff0c;这个位置往后的元素位置都要往后移动一次&#xff0c;元素插入的步骤有以下几步 &#xff08;1&#xff09;判断插入的位置是否合法&#xff0c;如果不合法则抛出异常 &#xff08;2&…...

Mac(m1)本地部署deepseek-R1模型

1. 下载安装ollama 直接下载软件&#xff0c;下载完成之后&#xff0c;安装即可&#xff0c;安装完成之后&#xff0c;命令行中可出现ollama命令 2. 在ollama官网查看需要下载的模型下载命令 1. 在官网查看deepseek对应的模型 2. 选择使用电脑配置的模型 3. copy 对应模型的安…...

Docker 部署 redis | 国内阿里镜像

一、简易单机版 1、镜像拉取 # docker hub 镜像 docker pull redis:7.0.4-bullseye # 阿里云镜像 docker pull alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/redis_optimized:20240221-6.2.7-2.3.0 2、运行镜像 docker run -itd --name redis \n …...

48V电气架构全面科普和解析:下一代智能电动汽车核心驱动

48V电气架构&#xff1a;下一代智能电动汽车核心驱动 随着全球汽车产业迈入电动化、智能化的新时代&#xff0c;传统12V电气系统逐渐暴露出其无法满足现代高功率需求的不足。在此背景下&#xff0c;48V电气架构应运而生&#xff0c;成为现代电动汽车&#xff08;EV&#xff09…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...