从C的角度接触到dynamic_cast

从C的角度接触到dynamic_cast

从C的角度接触到dynamic_cast

dynamic_cast关键字

写这篇文章的原因是因为笔者在遇到dynamic_cast时在网上查询文章资料讲解的都不是很清楚,至少对于笔者这种没有系统学习C++的人来说,由于之前一直是使用C语言开发,所以很多思想停留在C阶段,所以笔者在看了其他文章后通过与AI沟通逐渐清晰了dynamic_cast,并写下这篇文章希望对于没有系统接触过C++(东学一下西学一下😂)的伙伴们有所帮助

笔者的知识背景:在C语言中,对于一个确定类型的指针的使用基本上都是指向一个确定的变量实体,如果需要强制类型转换需要分析两个类型的内存空间是否相同,以及强制类型转换需要额外注意野指针的出现,通常使用的都是void *指向或者是char *指向,而对于为什么要用一个类型(非void)指针去指向另一个类型指针显得很不理解。

dynamic_castC++ 的运行时安全类型转换,只适用于带有虚函数的类层次结构(即多态类型),并且会 在运行时检查对象的实际类型是否真的可以转换

dynamic_cast应用场景

✅ 场景:安全地“向下转型”(Downcasting)

当有一个 基类指针/引用,但实际指向的是某个派生类对象,想把它转回派生类类型,以便调用派生类特有的成员函数

🔑 关键点dynamic_cast 会在 运行时检查 ptr 指向的对象是否真的是 Derived(或其子类)。如果不是,返回 nullptr(对指针)或抛出 std::bad_cast(对引用)。

❓所提出的问题本质是:

“既然我知道要操作的是 Derived 对象,为什么不直接用 Derived*?为什么先用 Base* 指向它,再费劲用 dynamic_cast 转回来?这不是多此一举吗?甚至用 void* 不也行?”

这个问题问得非常好!如果在写代码时 100% 确定对象类型,确实不需要 dynamic_cast

但现实中的程序往往不知道具体类型——而这正是 dynamic_cast 存在的意义。

✅ 为什么用基类指针指向派生类对象?

这是 多态的经典用法,目的是 “统一接口,不同实现”

🌰 举个实际例子:

假设写一个图形绘制系统:

现在把所有图形存到一个容器里统一管理:

👉 只能用 Shape*(基类指针)来存储它们,因为 vector 只能存同一种类型!

当遍历绘制时:

✅ 这时,并不知道 每个 shape 具体是 Circle 还是 Rectangle

❓但万一想调用派生类特有方法呢?比如给某个 Circle 设置半径?

这时候你就需要 Shape* 转回 Circle*

🔑 关键点:拿到这个指针的时候,已经“丢失”了具体类型信息,只知道它是 Shape

✅ 什么时候你会“不知道类型”?

这在以下场景非常常见:

场景说明
容器统一存储如上例,vector<Base*>存多种派生类
回调函数/事件系统回调传入的是Base*,但具体类型由触发方决定
插件系统主程序只认识接口Base,插件提供Derived1/2/3
反序列化/工厂模式从文件或网络加载对象,只知道基类类型
GUI 框架所有控件继承自Widget,但实际是ButtonTextBox

在这些场景中,代码的编写者在编译时根本不知道运行时会拿到什么具体类型

 

上一篇
下一篇