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_cast 和 static_cast 的区别
| 比较项 | dynamic_cast | static_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 的最佳场景
- 向下转换(基类指针/引用 → 派生类指针/引用)。
- 运行时类型检查(避免
static_cast可能的未定义行为)。 - 接口类(如
Base* ptr指向某个不确定类型的派生类,需要判断其类型)。
❌ 避免 dynamic_cast 的情况
- 不涉及多态(没有
virtual函数,dynamic_cast无法工作)。 - 已知类型安全的转换(可用
static_cast代替)。 - 高性能场景(
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_cast、dynamic_cast、const_cast、reinterpret_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*> 移除了 ptr 的 const 限定符,使得 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_cast 在 const 方法中修改成员变量
如果不能使用 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?
✅ 适用场景
- 调用旧 C 库时,避免
const兼容性问题(如const char*转char*)。 - 在
const成员函数中修改成员变量(但推荐mutable)。 - 特定场景下移除
const以提高灵活性(如优化某些代码)。
❌ 不推荐使用的情况
- 试图修改真正的
const变量(未定义行为)。 - 滥用
const_cast破坏const语义(影响代码可读性)。 - 可以使用
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。
🚀 最佳实践:
- 如果可能,避免
const_cast,使用mutable或者static_cast。 - 只有在调用 C 代码或
const兼容性问题时使用const_cast。 - 确保
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 运行时类型转换(RTTI, Run-Time Type Identification)的一部分,主要用于: 安全的多态类型转换检查类型的有效性向下转换(Downcasting)跨类层次的指针或引用…...
React进行路由跳转的方法汇总
在 React 中进行路由跳转有多种方法,具体取决于你使用的路由库和版本。以下是常见的路由跳转方法汇总,主要基于 react-router-dom 库。 1. 使用 useNavigate 钩子(适用于 react-router-dom v6) useNavigate 是 react-router-dom…...
python卷积神经网络人脸识别示例实现详解
目录 一、准备 1)使用pytorch 2)安装pytorch 3)准备训练和测试资源 二、卷积神经网络的基本结构 三、代码实现 1)导入库 2)数据预处理 3)加载数据 4)构建一个卷积神经网络 5࿰…...
以Unity6.0为例,如何在Unity中开启DLSS功能
DLSS DLSS(NVIDIA 深度学习超级采样):NVIDIA DLSS 是一套由 GeForce RTX™ Tensor Core 提供支持的神经渲染技术,可提高帧率,同时提供可与原生分辨率相媲美的清晰、高质量图像。目前最新突破DLSS 4 带来了新的多帧…...
CSDN 大模型 笔记
AI 3大范式:计算 发发 交互 L1 生成代码 复制到IDEA (22年12-23年6,7月份) L2 部分自动编程 定义class 设计interface 让其填充实现 (23年7,8月份) L3 通用任务 CRUD (24年) L4 高度自动编程 通用领域专有任务…...
Flink怎么保证Exactly - Once 语义
Exactly - Once 语义是消息处理领域中的一种严格数据处理语义,指每条数据都只会被精确消费和处理一次,既不会丢失,也不会重复。 以下从消息传递语义对比、实现方式、应用场景等方面详细介绍: 与其他消息传递语义对比 在消息传递…...
AOS安装及操作演示
文章目录 一、安装node1.1 在 macOS 上管理 Node版本1.1.1 安装 nvm1.1.2 验证 nvm 是否安装成功1.1.3 使用 nvm 安装/切换 Node.js 版本1.1.4 卸载 Node.js 版本 1.2 在 windows 上管理 Node版本1.2.1 安装 nvm-windows1.2.2 安装 Node.js 版本1.2.3 切换 Node.js 版本1.2.4 卸…...
Python 操作 MongoDB 教程
一、引言 在当今数字化时代,数据的存储和管理至关重要。传统的关系型数据库在处理一些复杂场景时可能会显得力不从心,而 NoSQL 数据库应运而生。MongoDB 作为一款开源的、面向文档的 NoSQL 数据库,凭借其高性能、高可扩展性和灵活的数据模型…...
Stability AI 联合 UIUC 提出单视图 3D 重建方法SPAR3D,可0.7秒完成重建并支持交互式用户编辑。
Stability AI 联合 UIUC 提出一种简单而有效的单视图 3D 重建方法 SPAR3D,这是一款最先进的 3D 重建器,可以从单视图图像重建高质量的 3D 网格。SPAR3D 的重建速度很快,只需 0.7 秒,并支持交互式用户编辑。 相关链接 论文…...
网易易盾接入DeepSeek,数字内容安全“智”理能力全面升级
今年农历新年期间,全球AI领域再度掀起了一波革命性浪潮,国产通用大模型DeepSeek凭借其强大的多场景理解与内容生成能力迅速“出圈”,彻底改写全球人工智能产业的格局。 作为国内领先的数字内容风控服务商,网易易盾一直致力于探索…...
自动驾驶---如何打造一款属于自己的自动驾驶系统
在笔者的专栏《自动驾驶Planning决策规划》中,主要讲解了行车的相关知识,从Routing,到Behavior Planning,再到Motion Planning,以及最后的Control,笔者都做了相关介绍,其中主要包括算法在量产上…...
局域网使用Ollama(Linux)
解决局域网无法连接Ollama服务的问题 在搭建和使用Ollama服务的过程中,可能会遇到局域网内无法连接的情况。经过排查发现,若开启了代理软件,尤其是Hiddify,会导致此问题。这一发现耗费了我数小时的排查时间,希望能给大…...
聚焦 AUTO TECH China 2025,共探汽车内外饰新未来Automotive Interiors
全球汽车产业蓬勃发展的大背景下,汽车内外饰作为汽车重要组成部分,其市场需求与技术创新不断推动着行业变革。2025年11月20日至22日,一场备受瞩目的行业盛会 ——AUTO TECH China 2025 广州国际汽车内外饰技术展览会将在广州保利世贸博览馆盛…...
Moretl 增量文件采集工具
永久免费: <下载> <使用说明> 用途 定时全量或增量采集工控机,电脑文件或日志. 优势 开箱即用: 解压直接运行.不需额外下载.管理设备: 后台统一管理客户端.无人值守: 客户端自启动,自更新.稳定安全: 架构简单,兼容性好,通过授权控制访问. 架构 技术架构: Asp…...
支持多种网络数据库格式的自动化转换工具——VisualXML
一、VisualXML软件介绍 对于DBC、ARXML……文件的编辑、修改等繁琐操作,WINDHILL风丘科技开发的总线设计工具——VisualXML,可轻松解决这一问题,提升工作效率。 VisualXML是一个强大且基于Excel表格生成多种网络数据库文件的转换工具&#…...
mysql8 用C++源码角度看客户端发起sql网络请求,并处理sql命令
MySQL 8 的 C 源码中,处理网络请求和 SQL 命令的流程涉及多个函数和类。以下是关键的函数和类,以及它们的作用: 1. do_command 函数 do_command 函数是 MySQL 服务器中处理客户端命令的核心函数。它从客户端读取一个命令并执行。这个函数在…...
四、OSG学习笔记-基础图元
前一章节: 三、OSG学习笔记-应用基础-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145514021 代码:CuiQingCheng/OsgStudy - Gitee.com 一、绘制盒子模型 下面一个简单的 demo #include<windows.h> #include<osg/Node&…...
使用vllm docker容器部署大语言模型
说明 最近deepseek比较火,我在一台4卡4090的服务器上尝试部署了一下,记录下部署步骤。 安装过程 安卓docker和nvidia-container-toolkit 安装19.03版本以上的docker-ce即可。安装步骤参考清华docker源上的安装步骤:Docker CE 软件仓库 为…...
window 安装GitLab服务器笔记
目录 视频: 资源: Linux CeneOS7: VMware: Linux无法安装 yum install vim -y 1.手动创建目录 2.下载repo PS 补充视频不可复制的代码 安装GitLab *修改root用户密码相关(我卡在第一步就直接放弃了这个操作&…...
MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 基础篇 part 10
第10章_创建和管理表 DDL:数据定义语言。CREATE \ALTER\ DROP \RENAME TRUNCATE DML:数据操作语言。INSERT \DELETE \UPDATE \SELECT(重中之重) DCL:数据控制语言。COMMIT \…...
react项目引入tailwindcss不生效解决方案
根据tailwindcss官网的操作步骤下来,样式未生效,且未报错,看了挺多的资料,还是并未解决。 后面在另一个项目尝试时,报了下面的问题: Error: PostCSS plugin tailwindcss requires PostCSS 8 根据这个链接…...
Expo运行模拟器失败错误解决(xcrun simctl )
根据你的描述,问题主要涉及两个方面:xcrun simctl 错误和 Expo 依赖版本不兼容。以下是针对这两个问题的解决方案: 解决 xcrun simctl 错误 错误代码 72 通常表明 simctl 工具未正确配置或路径未正确设置。以下是解决步骤: 确保 …...
【系统架构设计师】体系结构文档化
目录 1. 说明2. 重要性3. 主要内容4. 编写原则5. 实践建议6. 例题6.1 例题1 1. 说明 1.绝大多数的体系结构都是抽象的,由一些概念上的构建组成。2.层的概念在任何程序设计语言中都不存在。3.要让系统分析员和程序员去实现体系结构,还必须将体系结构进行…...
【0403】Postgres内核 检查(procArray )给定 db 是否有其他 backend process 正在运行
文章目录 1. 给定 db 是否有其他 backend 正在运行1.1 获取 allPgXact[] 索引1.1.1 MyProc 中 databaseId 初始化实现1.2 allProcs[] 中各 databaseId 判断1. 给定 db 是否有其他 backend 正在运行 CREATE DATABASE 语句创建用户指定 数据库名(database-name)时候, 会通过 …...
前端如何判断浏览器 AdBlock/AdBlock Plus(最新版)广告屏蔽插件已开启拦截
2个月前AdBlock/AdBlock Plus疑似升级了一次 因为自己主要负责面对海外的用户项目,发现以前的检测AdBlock/AdBlock Plus开启状态方法已失效了,于是专门研究了一下。并尝试了很多方法。 已失效的老方法 // 定义一个检测 AdBlock 的函数 function chec…...
微信小程序(第一集)
app.json {// 定义小程序的所有页面路径,数组中的第一个页面是首页"pages": ["pages/index/index", // 首页"pages/logs/logs" // 日志页面],// 设置小程序的全局窗口外观(比如导航栏和背景颜色)"wind…...
flutter ListView Item复用源码解析
Flutter 的 ListView 的 Item 复用机制是其高性能列表渲染的核心,底层实现依赖于 Flutter 的渲染管线、Element 树和 Widget 树的协调机制。以下是 ListView 复用机制的源码级解析,结合关键类和核心逻辑进行分析。 1. ListView 的底层结构 ListView 的复…...
《Operating System Concepts》阅读笔记:p9-p12
《Operating System Concepts》学习第 3 天,p9-p12 总结,总计 4 页。 一、技术总结 1.interrupt interrupt具有优先级(priority)。 2.storage 指令只能在 memory 上执行,所以要执行程序,那么就要加载到内存上。 (1)RAM Gen…...
html文件怎么转换成pdf文件,2025最新教程
将HTML文件转换成PDF文件,可以采取以下几种方法: 一、使用浏览器内置功能 打开HTML文件:在Chrome、Firefox、IE等浏览器中打开需要转换的HTML文件。打印对话框:按下CtrlP(Windows)或CommandP(M…...
【SpringBoot实现全局API限频】 最佳实践
在 Spring Boot 中实现全局 API 限频(Rate Limiting)可以通过多种方式实现,这里推荐一个结合 拦截器 Redis 的分布式解决方案,适用于生产环境且具备良好的扩展性。 方案设计思路 核心目标:基于客户端标识(…...
