C++显性契约与隐性规则:类型转换

C++显性契约与隐性规则:类型转换

文章目录

关于类型转换,通常是隐式转换或者强制转换,C++ 提供了一些能够显式表示转换的运算符,能够更好的规避一些风险和错误

1.传统的类型转换

C 语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化

voidTest(){int i =1;// 隐式类型转换double d = i;printf("%d, %.2f\n", i, d);int* p =&i;// 显示的强制类型转换int address =(int)p;printf("%x, %d\n", p, address);}

转换分为显式和隐式:

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
  2. 显式类型转化:需要用户自己处理

然而这两种转换的前提是逻辑相近:

  • 基本类型间的转换(如 intdouble
  • 继承层级中的转换(如子类→父类、父类→子类)
  • 用户定义的转换(如 operator T() 或带参数的构造函数)
string s; vector<int>=(vector<int>) s;

这种转换就会失败,因为逻辑不相近

对于强制转换还有一种特殊易错的场景

intmain(){constint n =10;int* p =(int*)&n;(*p)++; string s; vector<int>=(vector<int>) s; cout << n << endl; cout <<*p << endl;return0;}

无论是有点 C 语言基础的人,甚至是学完 C++ 的初学者,都很容易认为这里的输出结果是:n11*p11。但是结果并非所愿,输出结果:n10*p11

实际上这里涉及到存储规则的问题,因为 nconst 变量,那么会被识别为一个常变量,可能会是一个经常被使用的值,就把 n 存入寄存器,把频繁使用的变量的值暂存到寄存器中,这样在后续对该变量的读取操作中,就不需要每次都去内存中读取,直接从寄存器中获取即可,因为寄存器的读写速度比内存快很多

通常 cout 输出的值都是在内存里读取的,相比寄存器,内存读写速度较慢,但内存容量相对寄存器大很多,大多的代码都是存在这里的

因此这里输出的 n 是取自内存器,*p 取自内存

volatileconstint n =10;

volatile 关键字表示该变量的值可能会在程序未明确指定的情况下被改变,编译器不会对其进行优化,即不会被存入寄存器,这样取到的 n 就是内存中及时更新的值

C 风格的转换格式很简单,但是有不少缺点的:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

因此 C++ 提出了自己的类型转化风格,注意因为 C++ 要兼容 C 语言,所以 C++ 中还可以使用 C 语言的转化风格

2.C++强制类型转换

2.1 static_cast

intmain(){double d =12.34;int a =static_cast<int>(d); cout << a << endl;return0;}

static_cast 需要逻辑上的相近性

2.2 reinterpret_cast

intmain(){// 这里使用static_cast会报错,应该使用reinterpret_cast//int *p = static_cast<int*>(a);int* p =reinterpret_cast<int*>(a);return0;}

reinterpret_cast 几乎无类型限制,不要求类型相近,可强制转换任意指针或整数类型,但极其危险,可能导致:

  • 违反别名规则(如通过 char* 修改 int
  • 函数指针转换后调用,引发崩溃
  • 平台依赖(如不同架构的指针大小不同)

2.3 const_cast

voidTest(){volatileconstint a =2;int* p =const_cast<int*>(&a);*p =3; cout << a << endl;}

仅改变类型的 const / volatile 属性,这里用 reinterpret_cast 也不行的,因为 const 的转换是有风险的

2.4 dynamic_cast

classA{public:virtualvoidf(){}};classB:publicA{};voidfun(A* pa){// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回 B* pb1 =static_cast<B*>(pa); B* pb2 =dynamic_cast<B*>(pa); cout <<"pb1:"<< pb1 << endl; cout <<"pb2:"<< pb2 << endl;}intmain(){ A a; B b;fun(&a);fun(&b);return0;}

dynamic_cast 用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

  • 向上转型: 子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
  • 向下转型: 父类对象指针/引用->子类指针/引用(用 dynamic_cast 转型是安全的)

pa 是指向子类对象 B 的,转换可以成功,正常返回地址;pa 是指向父类对象 A 的,转换失败,返回空指针

🔥值得注意的是: 必须是继承关系中的类,基类必须包含虚函数

3.RTTI

RTTI:Run-time Type identification 的简称,即:运行时类型识别

C++ 通过以下方式来支持 RTTI

  1. typeid 运算符
  2. dynamic_cast 运算符
  3. decltype

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

Read more

GitHub 寻宝指南:四种高效发现优质开源项目的方法

GitHub 寻宝指南:四种高效发现优质开源项目的方法

文章目录 * 引言:从“收藏家”到“寻宝猎人”,升级你的 GitHub 发现技能 * 方法一:利用 GitHub 自身的功能(基础) * 1. GitHub Explore (探索) * 2. GitHub 高级搜索 * 方法二:借助社区整理的精选列表(高效) * 1. Awesome Lists * 2. 关注领域专家 * 方法三:善用第三方辅助网站(多维) * 1. Star History * 2. LibHunt * 方法四:拥抱 AI 进行智能搜索(前沿) * GitHub 的 AI 搜索 (Ask Copilot) * 实战演示: * 结语:

By Ne0inhk
IDEA和GIT实现cherry pick拣选部分变更到新分支

IDEA和GIT实现cherry pick拣选部分变更到新分支

前言 在工作中,当你出现一些情况,需要将一个分支的部分变动提取出来,只需要更新提取出来的情况就需要用到当前文章提到的git的功能 并且正常情况下,你工作是没有权限直接合并到生产分支,并且前一个需求还没合并到生产分支,如果你想要复用这部分的改动逻辑,那么就需要用到这个操作,也叫cherry-pick拣选 核心作用 核心作用是将一个或多个已有的提交(commit)复制到当前所在的分支上。 你可以把它想象成在一棵果树上,只挑选(pick)几颗你想要的,而不是把整根树枝都搬过来。 为什么需要它? 主要用于那些不需要合并整个分支,而只需要其中几个特定提交的情况。 将修复补丁应用到多个分支 这是最常见、最经典的场景。假设你有一个bugfix分支上修复了一个关键 bug,这个提交的 hash 是 a1b2c3d。现在你需要将这个修复同时应用到: main 分支(生产环境) develop 分支(开发环境) 可能还有旧的维护分支 v1.x 你不需要将整个 bugfix 分支合并到这些分支上,只需要在每个目标分支上执行: git cherry-pick a1b2c3d 意外在错

By Ne0inhk
夜莺-Nightingale-开源云原生监控分析系统部署 Prometheus 作为时序库使用(配置多数据源)

夜莺-Nightingale-开源云原生监控分析系统部署 Prometheus 作为时序库使用(配置多数据源)

夜莺-Nightingale-开源云原生监控分析系统部署 Prometheus 作为时序库使用(配置多数据源) * 一、前言 * 二、Prometheus安装步骤 * 1. 下载并安装Prometheus * 2. 关键配置:启用Remote Write接收器 * 3. 创建Systemd服务 * 4. 启动并验证服务 * 三、验证Remote Write功能 * 四、修改夜莺配置文件对接时序库 * 1. 再增加一个Prometheus 时序库。 * 2. 重启夜莺监控(N9E)服务: * 3. 夜莺数据源管理新增数据源 * 五、常见问题解决 * 1. 夜莺转发数据时报404错误 * 2. 权限问题 * 3. 端口冲突 * 六、总结 * 参考链接 💐The Begin💐点点关注,收藏不迷路💐 一、前言 Prometheus是一款开源的监控系统和时序数据库,

By Ne0inhk
今日AI榜单速览(GitHub Trending AI Top3)

今日AI榜单速览(GitHub Trending AI Top3)

🔥 个人主页:杨利杰YJlio❄️ 个人专栏:《Sysinternals实战教程》《Windows PowerShell 实战》《WINDOWS教程》《IOS教程》《微信助手》《锤子助手》《Python》《Kali Linux》《那些年未解决的Windows疑难杂症》🌟 让复杂的事情更简单,让重复的工作自动化 今日AI热榜 * 1 1 今日榜单速览(GitHub Trending AI Top3) * 2 2 ruvnet / RuView:WiFi DensePose 的“无线透视”路线 * 2 我的一句话总结 * 2 为什么今天它能冲到第一? * 2 图:它的可视化界面长这样(很直观) * 2 我如何最快验证(不折腾工具链) * 3 3 K-Dense-AI / claude-scientific-skills:给

By Ne0inhk