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

C++ 类型转换

1. static_cast

用于进行比较“自然”和低风险的转换,如整型和浮点型、字符型之间的互相转换。另外,如果对象所属的类重载了强制类型转换运算符 T(如 T 是 int、int* 或其他类型名),则 static_cast 也能用来进行对象到 T 类型的转换。

static_cast 不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换。因为这些属于风险比较高的转换。

A a; int n; char* p = "New Dragon Inn"; n = static_cast<int>(3.14); // n 的值变为 3 n = static_cast<int>(a); //调用 a.operator int,n 的值变为 1 p = static_cast<char*>(a); //调用 a.operator char*,p 的值变为 NULL n = static_cast<int>(p); //编译错误,static_cast不能将指针转换成整型 p = static_cast<char*>(n); //编译错误,static_cast 不能将整型转换成指针

2. dynamic_cast

进行类层次间的下行转换时更加安全

dynamic_cast 运算符可以在执行期决定真正的类型。如果下行转换是安全的(也就是说,如果基类指针或者引用确实指向一个派生类对象),这个运算符会传回转型过的指针。如果下行转换不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。

说了这么多是什么意思呢?总结可以是两句话:

(1) 在类层次间进行上行转换时,dynamic_cast 和 static_cast 的效果是一样的。

(2) 在类层次间进行下行转换时,dynamic_cast 具有类型检查的功能,比 static_cast 更安全。

Base b; Derived d; Derived* pd; pd = reinterpret_cast <Derived*> (&b); if (pd == NULL) //此处pd不会为 NULL。reinterpret_cast不检查安全性,总是进行转换 cout << "unsafe reinterpret_cast" << endl; //不会执行 pd = dynamic_cast <Derived*> (&b); if (pd == NULL) //结果会是NULL,因为 &b 不指向派生类对象,此转换不安全 cout << "unsafe dynamic_cast1" << endl; //会执行 pd = dynamic_cast <Derived*> (&d); //安全的转换 if (pd == NULL) //此处 pd 不会为 NULL cout << "unsafe dynamic_cast2" << endl; //不会执行

3. reinterpret_cast

用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。转换时,执行的是逐个比特复制的操作。

这种转换提供了很强的灵活性,但转换的安全性只能由程序员的细心来保证了。例如,程序员执意要把一个 int* 指针、函数指针或其他类型的指针转换成 string* 类型的指针也是可以的,至于以后用转换后的指针调用 string 类的成员函数引发错误,程序员也只能自行承担查找错误的烦琐工作。

A a(100); int &r = reinterpret_cast<int&>(a); //强行让 r 引用 a r = 200; //把 a.i 变成了 200 cout << a.i << "," << a.j << endl; // 输出 200,100 int n = 300; A *pa = reinterpret_cast<A*> ( & n); //强行让 pa 指向 n pa->i = 400; // n 变成 400 pa->j = 500; //此条语句不安全,很可能导致程序崩溃 cout << n << endl; // 输出 400 long long la = 0x12345678abcdLL; pa = reinterpret_cast<A*>(la); //la太长,只取低32位0x5678abcd拷贝给pa unsigned int u = reinterpret_cast<unsigned int>(pa);//pa逐个比特拷贝到u cout << hex << u << endl; //输出 5678abcd typedef void (* PF1) (int); typedef int (* PF2) (int,char *); PF1 pf1; PF2 pf2; pf2 = reinterpret_cast<PF2>(pf1); //两个不同类型的函数指针之间可以互相转换

4. const_cast

用于进行去除 const 属性的转换

const string s = "Inception"; string& p = const_cast <string&> (s); string* ps = const_cast <string*> (&s); // &s 的类型是 const string*

5. bad_cast

由于强制转换为引用类型失败,dynamic_cast 运算符引发 bad_cast 异常。

try { Circle& ref_circle = dynamic_cast<Circle&>(ref_shape); } catch (bad_cast b) { cout << "Caught: " << b.what(); }

6. 智能指针转换

使用std::dynamic_pointer_caststd::static_pointer_cast

#include <iostream> #include <memory> class base { public: // 一定要定义这个虚析构函数,否则基类无法转换为派生类 virtual ~base() = default; }; class derived : public base { }; int main(void) { // 定义两个不同的派生类对象 std::shared_ptr<derived> derived_obj = std::make_shared<derived>(); // 隐式转换 derived->base std::shared_ptr<base> pointer1 = derived_obj; // static_pointer_cast derived->base std::shared_ptr<base> pointer2 = std::static_pointer_cast<base>(derived_obj); // dynamic_pointer_cast base->derived std::shared_ptr<derived> pointer3 = std::dynamic_pointer_cast<derived>(pointer1); std::cout << (pointer3.get() == nullptr) << std::endl; // dynamic_pointer_cast base->derived auto pointer4 = std::dynamic_pointer_cast<test>(pointer1); std::cout << (pointer4.get() == nullptr) << std::endl; return 0; }

参考文献

c++ dynamic_cast 和 static_cast 的区别-CSDN博客

https://zhuanlan.zhihu.com/p/35153051

https://stackoverflow.com/questions/16374671/cannot-dynamic-cast-when-using-dynamic-pointer-cast

C++强制类型转换运算符(static_cast、reinterpret_cast、const_cast和dynamic_cast) - C语言中文网

http://www.jsqmd.com/news/1160965/

相关文章:

  • 维度建模实战:电商数仓 4 层架构设计,从 ODS 到 ADS 的完整落地流程
  • 2026年医疗器械EMC安规检测服务商盘点、实力解析与合规选型避坑指南 - 产业观察报
  • STM32F429ZI与EM3080-W条形码识别系统设计
  • 秒杀系统如何设计
  • RedisDesktopManager Windows终极指南:告别命令行,3分钟搭建可视化Redis管理平台
  • 3分钟极速体验:这款免费浏览器扩展让你的GitHub下载速度飙升10倍
  • 终极指南:如何用MCA Selector轻松管理你的Minecraft世界存档
  • 高精度ADC系统设计:ADS131M02与PIC18F86J15的工程实践
  • 程序员必读书单
  • d3d8to9:让Direct3D 8游戏在Windows 10/11上完美运行的终极解决方案
  • 数学学习指南
  • 江诗丹顿中国官方售后服务中心|最新网点地址及官网热线权威公布(2026年7月最新) - 江诗丹顿中国服务中心
  • OneMore插件技术解析:深度重构OneNote生产力的架构设计与实现路径
  • 化工涂料公司怎么做GEO:AI引用逻辑、服务商选择、具体操作、效果监控全流程分享,全程零代码SAAS
  • JavaScript 网盘文件直链获取技术方案:重构下载体验的现代实现
  • PLIP完全指南:如何通过3种方法高效分析蛋白质-配体相互作用
  • 直流有刷电机驱动器TC78H651AFNG与PIC18LF47K40应用解析
  • C++ 运行问题汇总
  • 免费论文下载网址
  • Ubuntu 终端
  • 程序员开会做纪要,2026年3款带免费额度视频导出文字工具够用吗
  • Flask+flask-socketio+jsonrpc组合配置避坑
  • Wand-Enhancer:免费解锁WeMod高级功能的本地化增强方案
  • 网盘直链下载助手:九大平台真实下载地址一键获取终极指南
  • 基于MA12070与STM32L4A6RG的高保真音频系统设计
  • MGBX全球社区建设提速,持续完善Web3生态版图
  • Kimi vs ChatGPT:从API成本、Token计费、企业级合规审计到私有化部署——一份让CTO连夜重做采购决策的对比报告
  • 如何快速上手PilotGo-plugin-syscare:5分钟完成热补丁部署
  • JSON解析
  • LV3296与MKV44F64VLH16嵌入式数据采集系统开发指南