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 略低
  • 适用于事件处理、插件系统等场景,但不建议在高性能代码中滥用。

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

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

相关文章

Qt文本高亮显示【QSyntaxHighlighter】功能代码讲解

QSyntaxHighlighter 是 Qt 框架中的一个重要类&#xff0c;专门用于为文本内容提供语法高亮功能。它广泛应用于文本编辑器、代码编辑器、日志查看器等应用程序中&#xff0c;允许开发者对文本中的不同部分应用不同的格式&#xff0c;如字体颜色、背景色、加粗等。通过这个类&am…

MS08067练武场--WP

免责声明&#xff1a;本文仅用于学习和研究目的&#xff0c;不鼓励或支持任何非法活动。所有技术内容仅供个人技术提升使用&#xff0c;未经授权不得用于攻击、侵犯或破坏他人系统。我们不对因使用本文内容而引起的任何法律责任或损失承担责任。 注&#xff1a;此文章为快速通关…

WPF正则表达式验证输入是否包含中文字母数字,不能是纯符号

1、验证纯中文 string pattern "[\u4e00-\u9fa5]"; // 创建Regex对象 Regex regex new Regex(pattern); // 判断输入字符串是否包含中文 if (!regex.IsMatch(name)) { //resultTextBlock.Text …

【Matlab优化算法-第13期】基于多目标优化算法的水库流量调度

一、前言 水库流量优化是水资源管理中的一个重要环节&#xff0c;通过合理调度水库流量&#xff0c;可以有效平衡防洪、发电和水资源利用等多方面的需求。本文将介绍一个水库流量优化模型&#xff0c;包括其约束条件、目标函数以及应用场景。 二、模型概述 水库流量优化模型…

《qt open3d中添加随机点采样》

qt open3d中添加随机点采样 效果展示二、流程三、代码效果展示 二、流程 创建动作,链接到槽函数,并把动作放置菜单栏 参照前文 三、代码 1、槽函数实现 void on_actionFilterRandomDownSample_triggered();void MainWindow::on_act

【图片转换PDF】多个文件夹里图片逐个批量转换成多个pdf软件,子文件夹单独合并转换,子文件夹单独批量转换,基于Py的解决方案

建筑设计公司在项目执行过程中&#xff0c;会产生大量的设计图纸、效果图、实景照片等图片资料。这些资料按照项目名称、阶段、专业等维度存放在多个文件夹和子文件夹中。 操作需求&#xff1a;为了方便内部管理和向客户交付完整的设计方案&#xff0c;公司需要将每个项目文件…

Windows 安装 DeepSeek 教程和open webui 图形化部署(非docker)

Windows 安装 Ollama : 步骤 1&#xff1a;下载并安装 Ollama 官网&#xff1a;奥拉马 点击下载 选择windows版本。 双击安装包 点击【Install】&#xff08;注意&#xff1a;安装包是直接安装在C盘的&#xff0c;并不支持更改路径&#xff0c;因此C盘的空间必须要至少大于5…

每日学习 设计模式 五种不同的单例模式

狮子大佬原文 https://blog.csdn.net/weixin_40461281/article/details/135050977 第一种 饿汉式 为什么叫饿汉,指的是"饿" 也就是说对象实例在程序启动时就已经被创建好,不管你是否需要,它都会在类加载时立即实例化,也就是说 实例化是在类加载时候完成的,早早的吃…

OpenCV 相机标定流程指南

OpenCV 相机标定流程指南 前置准备标定流程结果输出与验证建议源代码 OpenCV 相机标定流程指南 https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html https://learnopencv.com/camera-calibration-using-opencv/ 前置准备 制作标定板&#xff1a;生成高精度棋…

没有服务器和显卡电脑如何本地化使用deepseek|如何通过API使用满血版deepseek

目录 一、前言二、使用siliconflow硅基流动 API密钥1、注册硅基流动2、创建API密钥3、下载AI客户端4、使用API密钥5、效果演示 三、使用deepseek官方API密钥1、创建API密钥2、使用API密钥3、效果演示 四、总结 一、前言 上篇文章我介绍了如何通过云服务器或者显卡电脑来本地化…

python+unity落地方案实现AI 换脸融合

先上效果再说技术结论&#xff0c;使用的是自行搭建的AI人脸融合库&#xff0c;可以离线不受限制无限次生成&#xff0c;有需要的可以后台私信python ai换脸融合。 TODO 未来的方向&#xff1a;3D人脸融合和AI数据训练 这个技术使用的是openvcinsighface&#xff0c;openvc…

windows + visual studio 2019 使用cmake 编译构建静、动态库并调用详解

环境 windows visual studio 2019 visual studio 2019创建cmake工程 1. 静态库.lib 1.1 静态库编译生成 以下是我创建的cmake工程文件结构&#xff0c;只关注高亮文件夹部分 libout 存放编译生成的.lib文件libsrc 存放编译用的源代码和头文件CMakeLists.txt 此次编译CMak…

【前端】几种常见的跨域解决方案代理的概念

几种常见的跨域解决方案&代理的概念 一、常见的跨域解决方案1. 服务端配置CORS&#xff08;Cross-Origin Resource Sharing&#xff09;&#xff1a;2. Nginx代理3. Vue CLI配置代理&#xff1a;4 .uni-app在manifest.json中配置代理来解决&#xff1a;5. 使用WebSocket通讯…

Git 分布式版本控制工具使用教程

1.关于Git 1.1 什么是Git Git是一款免费、开源的分布式版本控制工具&#xff0c;由Linux创始人Linus Torvalds于2005年开发。它被设计用来处理从很小到非常大的项目&#xff0c;速度和效率都非常高。Git允许多个开发者几乎同时处理同一个项目而不会互相干扰&#xff0c;并且在…

基于java手机销售网站设计和实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

GitHub Pages + Jekyll 博客搭建指南(静态网站搭建)

目录 &#x1f680; 静态网站及其生成工具指南&#x1f30d; 什么是静态网站&#xff1f;&#x1f4cc; 静态网站的优势⚖️ 静态网站 VS 动态网站 &#x1f680; 常见的静态网站生成器对比&#x1f6e0;️ 使用 GitHub Pages Jekyll 搭建个人博客&#x1f4cc; 1. 创建 GitHu…

1.【线性代数】——方程组的几何解释

一 方程组的几何解释 概述举例举例一1. matrix2.row picture3.column picture 概述 三种表示方法 matrixrow picturecolumn picture 举例 举例一 { 2 x − y 0 − x 2 y 3 \begin{cases} 2x - y 0 \\ -x 2y 3 \end{cases} {2x−y0−x2y3​ 1. matrix [ 2 − 1 − 1 …

ZZNUOJ(C/C++)基础练习1091——1100(详解版)⭐

目录 1091 : 童年生活二三事&#xff08;多实例测试&#xff09; C C 1092 : 素数表(函数专题&#xff09; C C 1093 : 验证哥德巴赫猜想&#xff08;函数专题&#xff09; C C 1094 : 统计元音&#xff08;函数专题&#xff09; C C 1095 : 时间间隔&#xff08;多…

innovus如何分步长func和dft时钟

在Innovus工具中&#xff0c;分步处理功能时钟&#xff08;func clock&#xff09;和DFT时钟&#xff08;如扫描测试时钟&#xff09;需要结合设计模式&#xff08;Function Mode和DFT Mode&#xff09;进行约束定义、时钟树综合&#xff08;CTS&#xff09;和时序分析。跟随分…

java高级知识之集合

前言 集合是java开发中的重点内容&#xff0c;需要掌握的东西很多&#xff0c;面试中可问的东西很多&#xff0c;无论是深度还是广度。集合框架中Collection对应的实现类如下所示&#xff0c;这些都是要完全掌握&#xff0c;一个可以分为三大类List集合、Set‘集合以及Map集合…