dynamic_cast和static_cast和const_cast

news2025/2/13 3:34:35

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 = 42
    return 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 库接口,必须接收非 const
    str[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.coloradmin.cn/o/2297133.html

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

相关文章

python卷积神经网络人脸识别示例实现详解

目录 一、准备 1&#xff09;使用pytorch 2&#xff09;安装pytorch 3&#xff09;准备训练和测试资源 二、卷积神经网络的基本结构 三、代码实现 1&#xff09;导入库 2&#xff09;数据预处理 3&#xff09;加载数据 4&#xff09;构建一个卷积神经网络 5&#xff0…

以Unity6.0为例,如何在Unity中开启DLSS功能

DLSS DLSS&#xff08;NVIDIA 深度学习超级采样&#xff09;&#xff1a;NVIDIA DLSS 是一套由 GeForce RTX™ Tensor Core 提供支持的神经渲染技术&#xff0c;可提高帧率&#xff0c;同时提供可与原生分辨率相媲美的清晰、高质量图像。目前最新突破DLSS 4 带来了新的多帧…

CSDN 大模型 笔记

AI 3大范式&#xff1a;计算 发发 交互 L1 生成代码 复制到IDEA &#xff08;22年12-23年6&#xff0c;7月份&#xff09; L2 部分自动编程 定义class 设计interface 让其填充实现 (23年7&#xff0c;8月份) L3 通用任务 CRUD (24年) L4 高度自动编程 通用领域专有任务&#xf…

Stability AI 联合 UIUC 提出单视图 3D 重建方法SPAR3D,可0.7秒完成重建并支持交互式用户编辑。

Stability AI 联合 UIUC 提出一种简单而有效的单视图 3D 重建方法 SPAR3D&#xff0c;这是一款最先进的 3D 重建器&#xff0c;可以从单视图图像重建高质量的 3D 网格。SPAR3D 的重建速度很快&#xff0c;只需 0.7 秒&#xff0c;并支持交互式用户编辑。 相关链接 论文&#xf…

网易易盾接入DeepSeek,数字内容安全“智”理能力全面升级

今年农历新年期间&#xff0c;全球AI领域再度掀起了一波革命性浪潮&#xff0c;国产通用大模型DeepSeek凭借其强大的多场景理解与内容生成能力迅速“出圈”&#xff0c;彻底改写全球人工智能产业的格局。 作为国内领先的数字内容风控服务商&#xff0c;网易易盾一直致力于探索…

自动驾驶---如何打造一款属于自己的自动驾驶系统

在笔者的专栏《自动驾驶Planning决策规划》中&#xff0c;主要讲解了行车的相关知识&#xff0c;从Routing&#xff0c;到Behavior Planning&#xff0c;再到Motion Planning&#xff0c;以及最后的Control&#xff0c;笔者都做了相关介绍&#xff0c;其中主要包括算法在量产上…

聚焦 AUTO TECH China 2025,共探汽车内外饰新未来Automotive Interiors

全球汽车产业蓬勃发展的大背景下&#xff0c;汽车内外饰作为汽车重要组成部分&#xff0c;其市场需求与技术创新不断推动着行业变革。2025年11月20日至22日&#xff0c;一场备受瞩目的行业盛会 ——AUTO TECH China 2025 广州国际汽车内外饰技术展览会将在广州保利世贸博览馆盛…

Moretl 增量文件采集工具

永久免费: <下载> <使用说明> 用途 定时全量或增量采集工控机,电脑文件或日志. 优势 开箱即用: 解压直接运行.不需额外下载.管理设备: 后台统一管理客户端.无人值守: 客户端自启动,自更新.稳定安全: 架构简单,兼容性好,通过授权控制访问. 架构 技术架构: Asp…

支持多种网络数据库格式的自动化转换工具——VisualXML

一、VisualXML软件介绍 对于DBC、ARXML……文件的编辑、修改等繁琐操作&#xff0c;WINDHILL风丘科技开发的总线设计工具——VisualXML&#xff0c;可轻松解决这一问题&#xff0c;提升工作效率。 VisualXML是一个强大且基于Excel表格生成多种网络数据库文件的转换工具&#…

四、OSG学习笔记-基础图元

前一章节&#xff1a; 三、OSG学习笔记-应用基础-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145514021 代码&#xff1a;CuiQingCheng/OsgStudy - Gitee.com 一、绘制盒子模型 下面一个简单的 demo #include<windows.h> #include<osg/Node&…

window 安装GitLab服务器笔记

目录 视频&#xff1a; 资源&#xff1a; Linux CeneOS7&#xff1a; VMware&#xff1a; Linux无法安装 yum install vim -y 1.手动创建目录 2.下载repo PS 补充视频不可复制的代码 安装GitLab *修改root用户密码相关&#xff08;我卡在第一步就直接放弃了这个操作&…

MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 基础篇 part 10

第10章_创建和管理表 DDL&#xff1a;数据定义语言。CREATE \ALTER\ DROP \RENAME TRUNCATE DML&#xff1a;数据操作语言。INSERT \DELETE \UPDATE \SELECT&#xff08;重中之重&#xff09; DCL&#xff1a;数据控制语言。COMMIT \…

前端如何判断浏览器 AdBlock/AdBlock Plus(最新版)广告屏蔽插件已开启拦截

2个月前AdBlock/AdBlock Plus疑似升级了一次 因为自己主要负责面对海外的用户项目&#xff0c;发现以前的检测AdBlock/AdBlock Plus开启状态方法已失效了&#xff0c;于是专门研究了一下。并尝试了很多方法。 已失效的老方法 // 定义一个检测 AdBlock 的函数 function chec…

html文件怎么转换成pdf文件,2025最新教程

将HTML文件转换成PDF文件&#xff0c;可以采取以下几种方法&#xff1a; 一、使用浏览器内置功能 打开HTML文件&#xff1a;在Chrome、Firefox、IE等浏览器中打开需要转换的HTML文件。打印对话框&#xff1a;按下CtrlP&#xff08;Windows&#xff09;或CommandP&#xff08;M…

科技查新过不了怎么办

“科技查新过不了怎么办&#xff1f;” “科技查新不通过的原因是什么&#xff1f;” 想必这些问题一直困扰着各位科研和学术的朋友们&#xff0c;尤其是对于查新经验不够多的小伙伴&#xff0c;在历经千难万险&#xff0c;从选择查新机构、填写线上委托单到付费&#xff0c;…

超详细的数据结构3(初阶C语言版)栈和队列。

文章目录 栈和队列1.栈1.1 概念与结构1.2 栈的实现 2. 队列2.1 概念与结构2.2 队列的实现 总结 栈和队列 1.栈 1.1 概念与结构 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进行插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶&#xff0c;另…

centos 7 关于引用stdatomic.h的问题

问题&#xff1a;/tmp/tmp4usxmdso/main.c:6:23: fatal error: stdatomic.h: No such file or directory #include <stdatomic.h> 解决步骤&#xff1a; 1.这个错误是因为缺少C编译器的标准原子操作头文件 stdatomic.h。在Linux系统中&#xff0c;我们需要安装开发工具…

Unity WebGL包体压缩

最近在开发webgl&#xff0c;踩了很多坑&#xff0c;先来说下包体的问题。 开发完之后发现unity将文件都合并到一个文件了&#xff0c;一共有接近100m。 这对网页端的体验来说是可怕的&#xff0c;因为玩家必须要加载完所有的文件才能进入&#xff0c;这样体验特别差。 于是想…

【对比测评】 .NET 应用的 Web 视图控件:DotNetBrowser 或 EO.WebBrowser

您是否需要 .NET 应用的 Web 视图控件&#xff1f;.NET 生态系统提供了很多东西&#xff0c;有免费的 Web 视图控件&#xff0c;既有开源的&#xff0c;也有专有的。还有一些商业 Web 视图 控件&#xff0c;也是企业经常选择的一种选项。 在这篇博文中&#xff0c;我们比较了商…

Redis 数据类型 String 字符串

Redis 中的 String 数据类型 是最基础且使用最广泛的数据类型之一。它本质上是一个字节序列&#xff0c;可以存储各种类型的数据&#xff0c;如字符串、整数、浮点数等&#xff0c;其字符串类型的值包含⼀般格式的字符串或者类似 JSON、XML 格式的字符串&#xff1b;还可以存储…