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

c++的四种类型转换(static_cast,reinterpret_cast,const_cast,dynamic_cast)详解和代码示例

1. static_cast

1.1 底层原理

  • 编译器在 编译阶段 完成类型转换的检查与生成转换代码
  • 对基本类型,可能直接插入指令(如 mov + 类型扩展/截断指令)
  • 对类层次结构中的指针转换(上行或下行),会按照已知的内存布局调整指针偏移量

1.2 常用场景

  1. 数值类型转换

    double d = static_cast<double>(42); // int -> double
    
  2. 枚举与整数转换

    enum Color { Red, Green, Blue };
    Color c = static_cast<Color>(1);
    
  3. 类层次中的安全上行转换

    Base* b = static_cast<Base*>(derivedPtr);
    
  4. 已知安全的向下转型(无运行时检查)

    Derived* d = static_cast<Derived*>(b); // 需确保 b 真指向 Derived
    

1.3 陷阱

  • 向下转型若对象真实类型不匹配,会导致 未定义行为
  • 不会去掉 const,需要配合 const_cast 才能同时做类型+修饰符的转换

2. dynamic_cast

2.1 底层原理

  • 依赖 RTTI(运行时类型信息),编译器会为 有虚函数的类 生成 虚表指针(vptr)
  • 转换时,dynamic_cast 会沿类层次查找,判断类型是否匹配
  • 指针转换失败返回 nullptr,引用转换失败抛 std::bad_cast

2.2 常用场景

  1. 多态向下转型(安全检查)

    if (auto d = dynamic_cast<Derived*>(basePtr)) {d->doSomething();
    }
    
  2. 交叉转换(Cross cast)

    • 用于多继承时,从一个基类跨到另一个基类
  3. 运行时类型判别

    if (dynamic_cast<Derived*>(b)) { /* 是 Derived */ }
    

2.3 陷阱

  • 必须是多态类(至少一个虚函数)
  • RTTI 关闭(-fno-rtti)时不可用
  • 性能比 static_cast 慢(运行时遍历虚表)

3. const_cast

3.1 底层原理

  • 编译器在语义分析阶段直接去掉 const / volatile 标志,不改变对象内存布局
  • 运行时不会生成额外指令(除了调用接口时参数类型变化)

3.2 常用场景

  1. 调用非 const 接口

    void modify(int* p);
    const int x = 10;
    modify(const_cast<int*>(&x)); // 不安全
    
  2. 配合遗留 API(C 接口)

    void legacy(char* buf);
    const char* s = "Hello";
    legacy(const_cast<char*>(s)); // 若修改字面量则 UB
    

3.3 陷阱

  • 对原本是常量的对象去掉 const 并修改,属于 未定义行为
  • 安全的前提:对象底层确实是可修改的

4. reinterpret_cast

4.1 底层原理

  • 编译器在 编译阶段 直接重解释指针或整数的二进制位,不做语义检查
  • 常用于类型系统之外的底层内存操作

4.2 常用场景

  1. 指针类型之间的转换

    void* p = malloc(4);
    int* ip = reinterpret_cast<int*>(p);
    
  2. 整数 ↔ 指针

    intptr_t addr = reinterpret_cast<intptr_t>(ip);
    
  3. 硬件寄存器访问 / 网络字节解析

    uint32_t val = 0x12345678;
    unsigned char* bytes = reinterpret_cast<unsigned char*>(&val);
    

4.3 陷阱

  • 结果强依赖平台字节序与内存对齐
  • 在不同类型之间转换后访问可能破坏严格别名规则(strict aliasing)

工程使用建议

  • 优先级推荐

    1. static_cast:最安全,首选
    2. dynamic_cast:运行时安全检查(必要时用)
    3. const_cast:仅在确实需要去掉 const 时用
    4. reinterpret_cast:除非底层操作,尽量避免
  • 组合使用:如果要同时做类型和 const 修饰符转换,建议分步:

    Derived* d = static_cast<Derived*>(const_cast<Base*>(cb));
    
  • 性能考虑:频繁调用 dynamic_cast 会影响性能,尤其在实时系统(如 SLAM)中

  • 代码可维护性:过多 reinterpret_cast 会让代码难以理解且难以移植


总结对比

转换方式编译期/运行期主要用途是否类型检查能否去 const安全性
static_cast编译期基本类型转换、已知安全的类层次转换编译期检查较安全
dynamic_cast运行期多态类的安全向下转型运行期检查安全(失败返回 nullptr)
const_cast编译期添加/移除 const/volatile编译期检查视情况而定
reinterpret_cast编译期低级别强制转换(指针、整数)编译期弱检查危险

实战应用示例

下面 6 工程场景的应用示例,涵盖从普通类型到多态类、底层内存操作以及和 C API 交互的情况,大家可以在 SLAM、驱动、图形等 C++ 项目时都能直接套用,直接进行更改,方便快捷。


示例 1:static_cast — 传感器数据类型转换

在 SLAM 系统中,IMU 数据通常是 int16_t(原始寄存器值),需要转换为 double(物理量)。

#include <iostream>
#include <cstdint>
using namespace std;struct IMUDataRaw { int16_t acc_x; };int main() {IMUDataRaw raw{ 16384 }; // 假设这是 1gdouble acc_x_g = static_cast<double>(raw.acc_x) / 16384.0; cout << "Acceleration X: " << acc_x_g << " g" << endl;
}

示例 2:dynamic_cast — 多态消息解码

SLAM 系统接收统一基类的消息,需要根据实际类型解析。

#include <iostream>
#include <memory>
using namespace std;struct MsgBase { virtual ~MsgBase() = default; };
struct LidarMsg : MsgBase { void process() { cout << "Process Lidar\n"; } };
struct IMUMsg : MsgBase { void process() { cout << "Process IMU\n"; } };void handleMsg(shared_ptr<MsgBase> msg) {if (auto lidar = dynamic_cast<LidarMsg*>(msg.get())) {lidar->process();} else if (auto imu = dynamic_cast<IMUMsg*>(msg.get())) {imu->process();} else {cout << "Unknown message\n";}
}int main() {handleMsg(make_shared<LidarMsg>());handleMsg(make_shared<IMUMsg>());
}

示例 3:const_cast — 与遗留 C API 交互

旧的激光雷达 SDK 可能没有 const 修饰,导致你传入的常量数据被拒绝。

#include <iostream>
using namespace std;// 模拟旧 C API
void lidar_process(char* buf) { cout << "Processing: " << buf << endl; }int main() {const char* frame = "LidarFrame";// 去掉 const 修饰以适配 API(底层不修改才安全)lidar_process(const_cast<char*>(frame));
}

示例 4:reinterpret_cast — 解析点云二进制数据

接收到的点云是网络字节流,需要直接 reinterpret 成结构体。

#include <iostream>
#include <cstdint>
using namespace std;#pragma pack(push, 1)
struct PointXYZ { float x, y, z; };
#pragma pack(pop)int main() {uint8_t buffer[sizeof(PointXYZ)] = {0x00,0x00,0x20,0x41, 0x00,0x00,0x48,0x42, 0x00,0x00,0x70,0x41};PointXYZ* pt = reinterpret_cast<PointXYZ*>(buffer);cout << "Point: " << pt->x << ", " << pt->y << ", " << pt->z << endl;
}

示例 5:组合使用 static_cast + const_cast

在类层次结构中,既要做类型转换,又要去掉 const。

#include <iostream>
using namespace std;struct Base { virtual ~Base() = default; };
struct Derived : Base { void work() { cout << "Derived work\n"; } };void process(const Base* b) {// 去掉 const 后向下转型auto d = static_cast<Derived*>(const_cast<Base*>(b));d->work();
}int main() {Derived obj;process(&obj);
}

示例 6:reinterpret_cast 用于硬件寄存器映射

嵌入式 SLAM(机器人)中访问传感器寄存器。

#include <iostream>
#include <cstdint>
using namespace std;volatile uint32_t fake_register = 0xAABBCCDD;int main() {volatile uint8_t* reg8 = reinterpret_cast<volatile uint8_t*>(&fake_register);cout << hex << "Low byte: 0x" << static_cast<int>(reg8[0]) << endl;
}

http://www.lryc.cn/news/618164.html

相关文章:

  • 【R语言数据分析开发指南】
  • C++学习之数据结构:AVL树
  • 干货分享|如何从0到1掌握R语言数据分析
  • Rust:构造函数 new() 如何进行错误处理?
  • Vue.js 响应接口:深度解析与实践指南
  • 《Auracast广播音频技术解析及未来路线图》 —蓝牙技术联盟 市场拓展经理 吴志豪 技术与市场经理 鲁公羽
  • 基于 Easy Rules 的电商订单智能决策系统:构建可扩展的业务规则引擎实践
  • 电商双 11 美妆数据分析总结
  • CTO如何通过录音转写和音频降噪,提升企业远程协作效率?
  • 数据分析与可视化
  • 阿里巴巴开源多模态大模型-Qwen-VL系列论文精读(一)
  • Spring Cloud系列—Config配置中心
  • B树索引和B+树索引有什么区别?
  • TinyVue表格重构性能优化详解
  • 从基础编辑器到智能中枢:OpenStation 为 VSCode 注入大模型动力
  • 人工智能+虚拟仿真,助推医学检查技术理论与实践结合
  • MySQL 索引:索引为什么使用 B+树?(详解B树、B+树)
  • 零知开源——基于STM32F407VET6和INA219的功率监测器设计与实现
  • ZKmall开源商城的容灾之道:多地域部署与故障切换如何守护电商系统
  • 【新启航】从人工偏差到机械精度:旋转治具让三维扫描重构数据重复精度提升至 ±0.01mm
  • 解决 HTTP 请求 RequestBody 只能被读取一次的问题
  • 医美产业科技成果展陈中心:连接微观肌肤世界与前沿科技的桥梁
  • 【机器学习】什么是DNN / MLP(全连接深度神经网络, Deep Neural Network / Multilayer Perceptron)?
  • 01. maven的下载与配置
  • http网页部署
  • 微算法科技(NASDAQ:MLGO)开发经典增强量子优化算法(CBQOA):开创组合优化新时代
  • 聆思duomotai_ap sdk适配dooiRobot
  • 基于SpringBoot的课程作业管理系统
  • 【论文阅读】从表面肌电信号中提取神经信息用于上肢假肢控制:新兴途径与挑战
  • iOS 签名证书全生命周期实战,从开发到上架的多阶段应用