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

C++ 强制类型转换

C++ 四大强制类型转换

转换类型使用范围访问权限继承关系要求多态支持额外说明
static_cast适用于相关类型之间的转换,如基类<->派生类指针转换、数值类型转换等需满足访问权限(如基类继承方式)必须有继承关系,且访问权限允许可用于多态类型,但不做运行时检查编译时转换,效率高,但对非法转换不安全,向下转型可能导致未定义行为
dynamic_cast用于多态类型的安全向下转型或跨类层次指针转换需满足访问权限必须是多态类(含虚函数),有继承关系支持,执行运行时类型检查转换失败时,指针返回 nullptr,引用抛异常,性能开销较大
const_cast用于去除或添加 const / volatile 修饰无访问权限限制不依赖继承关系不涉及多态只能修改类型修饰符,不能改变类型本质,去除 const 后修改对象导致未定义行为
reinterpret_cast任意类型指针或整数间的转换,极其底层和不安全无访问权限限制不要求继承关系不支持不安全,直接按二进制重新解释,通常用于系统底层、硬件交互等特殊场景,慎用

static_cast

编译期类型检查,适合“已知关系”的转换

error C2440: “static_cast”: 无法从“B *”转换为“A *”, 需要存在寄存关系

class A {};
class B {};
int main()
{B b;A* a = static_cast<A*>(&b);
}

reinterpret_cast

完全底层强转,仅改变解释方式,不改地址内容
不能用于普通类型转换,例如:int → float (float、int底层内存解析不一样)

const_cast

去除 const,解除只读属性

dynamic_cast

支持多态转换,需有虚函数,需要RTTI(运行阶段类型识别)
dynamic_cast运算符将使用一个指向基类的指针来生成一个指向派生类的指针;否则,该运算符返回0(空指针);

典型实现步骤
当执行 dynamic_cast<DestType*>(srcPtr) 时,编译器生成的底层代码大致会做以下操作:

  • (1) 检查空指针
    如果 srcPtr 是 nullptr,直接返回 nullptr。
  • (2) 检查静态类型兼容性
    如果 DestType 和 srcPtr 的静态类型(编译时类型)无关(非继承关系),直接返回 nullptr。
  • (3) 查询 RTTI
    通过 srcPtr 对象的虚函数表(vtable)找到其 RTTI 信息(通常是 type_info 结构体),获取实际对象的动态类型。
  • (4) 遍历继承树
    向下转型(Downcast):检查 DestType 是否是实际对象的基类或派生类。如果是派生类,计算指针偏移量并调整。
    侧向转型(Crosscast):在多重继承中,可能需要调整指针指向目标类的子对象。
  • (5) 返回结果
    如果类型兼容,返回调整后的指针。否则,返回 nullptr。
class B1 {
public:virtual void f1() {}int b1_data;
};class B2 {
public:virtual void f2() {}int b2_data;
};class D : public B1, public B2 {
public:virtual void f1() override {} // 覆盖 B1::f1virtual void fd() {}          // D 的新虚函数int d_data;
};
int main()
{B2* d = new B2();B1* pb2 = dynamic_cast<B1*>(d);D* pb2s = static_cast<D*>(d);
}

pb2 不能转换成功,创建的B2类型不能转成B1类型
pb2s 能转换成功,但是运行的时候会产线未定义行为,因为分内存的时候只是分配了B2的内存大小,但是强制转成D,变成使用了D的内存大小,可能会访问非法内存

下图:
pb2s直接按编译向前减了8个字节(static_cast编译器的时候就进行转换了)
在这里插入图片描述

问题

为什么 static_cast 能正确处理多继承向上转型?

(1) 编译器已知继承关系
在编译时,编译器 完全知道 Derived 的继承结构(包括基类的顺序和偏移量)。
static_cast 直接根据继承关系计算指针调整,无需运行时信息。

(2) 指针调整是确定的
在多继承中,基类子对象的偏移量是编译期常量。例如:
Base1 的偏移量 = 0(首个子对象)。
Base2 的偏移量 = sizeof(Base1)。
static_cast 会根据目标基类类型,自动计算正确的偏移量。

(3) 不涉及运行时类型检查
static_cast 不依赖 RTTI(Run-Time Type Information),完全在编译期完成转换。
因此,即使没有虚函数(无虚表),static_cast 也能正确工作。

对比 dynamic_cast

dynamic_cast 也能向上转型,但它是为 向下转型(Downcasting) 设计的,向上转型时会退化为 static_cast:
dynamic_cast 的向上转型没有额外作用,反而可能误导代码读者(让人误以为需要运行时检查)。
static_cast 更清晰、更高效。

Base1* pb1 = dynamic_cast<Base1*>(&d); // 等价于 static_cast

为什么 static_cast 不能安全用于向下转型?

虽然 static_cast 能正确处理向上转型,但 向下转型(Downcasting) 时存在风险:
static_cast 不会检查 pb2 是否真的指向 Derived 对象,直接按继承关系调整指针,可能导致非法内存访问。此时必须用 dynamic_cast:

Base2* pb2 = new Base2;  // 纯 Base2 对象
Derived* pd = static_cast<Derived*>(pb2); // 危险!
http://www.dtcms.com/a/277316.html

相关文章:

  • 【操作系统】strace 跟踪系统调用(一)
  • (LeetCode 每日一题) 2410. 运动员和训练师的最大匹配数(排序、双指针)
  • es里为什么node和shard不是一对一的关系
  • Augment AI 0.502.0版本深度解析:Task、Guidelines、Memory三大核心功能实战指南
  • 将 NumPy 数组展平并转换为 Python 列表
  • 1.1.5 模块与包——AI教你学Django
  • OpenLayers 入门指南【二】:坐标系与投影转换
  • 把 DNA 当 PCIe:一条 365 nt 链实现 64 Gbps 片上光互连——基于链式 Förster 共振的分子级波分复用链路
  • 理解 Robots 协议:爬虫该遵守的“游戏规则”
  • MySQL逻辑删除与唯一索引冲突解决
  • M00224-小范围疫情防控元胞自动机模拟matlab
  • 【unitrix】 5.1 第二套类型级二进制数基本结构体(types2.rs)
  • 深入解析Hadoop架构设计:原理、组件与应用
  • OpenLayers使用
  • (2)从零开发 Chrome 插件:实现 API 登录与本地存储功能
  • 音视频学习(三十八):像素与位深
  • 打破并发瓶颈:虚拟线程实现详解与传统线程模型的性能对比
  • QuickUnion优化及Huffman树
  • JS红宝书pdf完整版
  • JAVA生成PDF(itextpdf)
  • 为什么玩游戏用UDP,看网页用TCP?
  • [2025CVPR]GNN-ViTCap:用于病理图像分类与描述模型
  • MyBatis框架进阶指南:深入理解CRUD与参数映射
  • Redis集群方案——哨兵机制
  • 无需付费即可利用AI消除音频噪声和生成字幕
  • 《Linux篇》自动化构建-make/Makefile
  • GraphRAG Docker化部署,接入本地Ollama完整技术指南:从零基础到生产部署的系统性知识体系
  • AI抠图软件,本地运行超快速
  • 水往低处流,人也往低处走
  • 三种网络类型