【C++】类型转换

【C++】类型转换

目录

C语言中的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。
(1)隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败。
(2)显式类型转化:需要用户自己处理。

classA{public:A()=default;};classB{ A _a;public:B(const A& a):_a(a){}};intmain(){int a =1;double b = a;float c = a;int* d =(int*)a;// 没法隐式转换,但是两者之间还是有点关系,所以可以强转 std::string str;// std::vector arr = str; 如果两者之间没有一点关系,那么就不能转换 A ca; B ca = ca;// 但是如果构成隐式类型转换,则可以转换return0;}

其实我们也能明白C语言的这种转换方式可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。尤其是隐式类型转换,有时不注意还会引发错误,比如

int pos =0; size_t sz =0;while(pos >= sz)// 死循环,pos整形提升成size_t,此时没有负数{ std::cout <<"hello world"<< std::endl;--pos;}

C风格的转换格式很简单,但是有不少缺点的:
(1)隐式类型转化有些情况下可能会出问题:比如数据精度丢失
(2)显式类型转换将所有情况混合在一起,代码不够清晰
因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的
转化风格。

C++强制类型转换

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:
static_castreinterpret_castconst_castdynamic_cast

static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。

int a =1;double b =static_cast<double>(a);

reinterpret_cast

reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型。比如int转指针,指针转int,不同类型指针转换,不同引用转换。reinterpret_cast不改变原有内存,只是改变内存数据的解释方式,比如我们可以这样

float a =3.1415926;int b =reinterpret_cast<int&>(a);// 打印结果: 1078530010int c =static_cast<int>(a);// 打印结果: 3 std::cout << b << std::endl; std::cout << c << std::endl;

这里我们使用引用转换将float 类型转换成int&,注意这里不能写int,因为reinterpret_cast不能进行值类型之间的直接转换,这是static_cast干的事,我们转换成int&,意思就是float底层存在内存中的数据没有改,只是将这段数据解释成了int,这里我们也能用int&来接收,这样就少一次拷贝。我们也能看到打印结果不会像static_cast那样,因为float的存储原理和int不一样。

const_cast

我们先来看下面这段代码,

constint a =1;int* b =(int*)&a;(*b)++; std::cout << a << std::endl;// 打印结果: 1 std::cout <<*b << std::endl;// 打印结果: 2

这是什么原因呢?a的类型是const int,是常变量,有存储空间,但是因为const不允许修改,所以编译器优化,将其视为常量,转成汇编之后直接就是常量数字,优化进了指令或者寄存器中了,所以当其数值被修改时内存中的数值已经被改了,但是打印时却无法显示,

 std::cout << a << std::endl;// 打印结果: 100007FF6AB9B196B mov edx,100007FF6AB9B1970 mov rcx,qword ptr [__imp_std::cout(07FF6AB9C1188h)]00007FF6AB9B1977 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char>>::operator<<(07FF6AB9C1190h)]00007FF6AB9B197D mov qword ptr [rbp+0F8h],rax 00007FF6AB9B1984 lea rdx,[std::endl<char,std::char_traits<char>>(07FF6AB9B1442h)]00007FF6AB9B198B mov rcx,qword ptr [rbp+0F8h]00007FF6AB9B1992 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char>>::operator<<(07FF6AB9C1118h)]00007FF6AB9B1998 nop 

可以看到移到寄存器的操作直接用的常量数字,所以这时出现了这样诡异的现象。想要避免的话也很简单,我们使用volatile关键字,

volatileconstint a =1;int* b =(int*)&a;(*b)++; std::cout << a << std::endl;// 打印结果: 2 std::cout <<*b << std::endl;// 打印结果: 2
 std::cout << a << std::endl;// 打印结果: 200007FF68B9B196B mov edx,dword ptr [a]00007FF68B9B196E mov rcx,qword ptr [__imp_std::cout(07FF68B9C1188h)]00007FF68B9B1975 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char>>::operator<<(07FF68B9C1190h)]00007FF68B9B197B mov qword ptr [rbp+0F8h],rax 00007FF68B9B1982 lea rdx,[std::endl<char,std::char_traits<char>>(07FF68B9B1442h)]00007FF68B9B1989 mov rcx,qword ptr [rbp+0F8h]00007FF68B9B1990 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char>>::operator<<(07FF68B9C1118h)]00007FF68B9B1996 nop 

它的作用就是让编译器编译时不要优化,每次都去内存中取数据。

我们也能发现,这种const类型指针转非const类型指针的操作虽然合法,但是是比较危险的,所以我们使用reinterpret_cast是无法对这种情况进行转换的,如果我们想要转换,我们就要使用const_cast。C++这么做的本意就是当我们要转换时,使用const_cast也算是一种提醒,告诉我们这样的操作是危险的,做好准备,比如加上volatile关键字。

volatileconstint a =1;//int* b = reinterpret_cast<int*>(&a);int* b =const_cast<int*>(&a);(*b)++; std::cout << a << std::endl;// 打印结果: 2 std::cout <<*b << std::endl;// 打印结果: 2

dynamic_cast

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)。
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)。
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)。
注意:
(1)dynamic_cast只能用于父类含有虚函数的类。
(2)dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0。
我们在对父子类指针 / 引用对象的进行转换时,可以使用dynamic_cast、或者static_cast,也能使用reinterpret_cast(可以但是不推荐,可能出问题),但是更提倡使用dynamic_cast。在进行向上转换时,其实由于继承的切片规则,怎么写都行,static_castreinterpret_cast,甚至直接赋值也行。但是如果是向下转换的话,可能就会有问题,因为上述的几种方法都不能很好的分辨这个父类指针 / 引用到底指向的父类还是子类,如果是父类,那就出错了,可能会有越界访问的情况,如果是子类就没事。这时我们使用dynamic_cast,它可以检查这个指针 / 引用指向的到底是父类还是子类,如果是父类,那么转换的是指针的话就会返回nullptr,如果是引用就会抛出异常,这样我们就能防止不当转换的错误发生。

RTTI

RTTI:Run-time Type identification的简称,即:运行时类型识别。
C++通过以下方式来支持RTTI:
(1)typeid运算符
(2)dynamic_cast运算符
(3)decltype
我们上面的dynamic_cast是怎么实现RTTI的呢?这其实就和它规定必须的是有虚函数才能进行转换有关系,我我们都知道,父类定义虚函数实现多态那么就会在存储时生成一张虚函数表,我们可以理解为这个虚函数标准额外有一个标记,标注了其是父类还是子类,这样我们在使用dynamic_cast进行转换时,就会进行运行时类型检查,看这个标记位,这样就能知道到底是父类还是子类了。

Read more

260223-Gartner Hype Cycle 2026 AI 报告调研与解读

260223-Gartner Hype Cycle 2026 AI 报告调研与解读

2026年人工智能技术成熟度曲线战略报告与深度总结 在2026年的全球科技版图中,人工智能(AI)正经历着从“技术狂热”向“运营务实”的根本性转变。根据行业领先的分析机构研究,2026年被界定为人工智能进入“幻灭期”(Trough of Disillusionment)的关键节点1。这一阶段并非预示着技术的失败,而是一次必要的情绪修正和市场洗礼。企业不再盲目追求宏大的“登月计划”,转而将注意力集中在可预测的投资回报率(ROI)、系统架构的稳健性以及跨职能的运营集成上1。与此同时,2026年也标志着人工智能从单一的模型应用演变为复杂的智能系统协同,通过代理式AI(Agentic AI)、多代理系统(Multiagent Systems)以及主权AI(Sovereign AI)等核心趋势,重新定义了全球商业竞争的规则3。 第一部分:2026年全球AI经济格局与支出分析 2026年全球人工智能支出预计将达到2.52万亿美元,较2025年增长44%1。这一巨大的财务投入反映了企业对AI基础设施建设的持续承诺。尽管市场处于幻灭期,但这种增长主要由技术供应商构建AI基础架构的战略驱动,基础

By Ne0inhk
Flutter 组件 genkit 的适配 鸿蒙Harmony 实战 - 驾驭大模型开发套件、实现鸿蒙端 AI 智能流式响应与提示词工程自动化方案

Flutter 组件 genkit 的适配 鸿蒙Harmony 实战 - 驾驭大模型开发套件、实现鸿蒙端 AI 智能流式响应与提示词工程自动化方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 genkit 的适配 鸿蒙Harmony 实战 - 驾驭大模型开发套件、实现鸿蒙端 AI 智能流式响应与提示词工程自动化方案 前言 在鸿蒙(OpenHarmony)生态向智能化、全场景自动化的演进过程中,“生成式 AI(Generative AI)”不再仅仅是一个噱头,而是重塑应用交互逻辑的核心底座。面对日益复杂的 LLM(大语言模型)调用链路、层出不穷的提示词(Prompt)版本管理以及对实时流式响应(Streaming)的严苛要求。如果仅仅依靠原始的 HTTP POST 请求。那么不仅会导致开发效率极低。更难以应对 AI 业务中常见的“幻觉审计”与“多模型动态切换”等高阶挑战方案。 我们需要一种“开发者友好、

By Ne0inhk
人工智能:自然语言处理与计算机视觉的融合应用

人工智能:自然语言处理与计算机视觉的融合应用

人工智能:自然语言处理与计算机视觉的融合应用 学习目标 💡 理解自然语言处理(NLP)与计算机视觉(CV)融合的基本概念和重要性 💡 掌握NLP与CV融合的主要方法和技术 💡 学会使用前沿模型(如CLIP、ALIGN、ViLT)进行多模态融合 💡 理解融合应用的场景(如图像字幕生成、视觉问答、多模态检索) 💡 通过实战项目,开发一个图像字幕生成应用 重点内容 * NLP与CV融合的基本概念 * 主要融合方法和技术 * 前沿融合模型(CLIP、ALIGN、ViLT) * 融合应用场景(图像字幕生成、视觉问答、多模态检索) * 实战项目:图像字幕生成应用开发 一、NLP与CV融合的基本概念 1.1 多模态学习的重要性 多模态学习(Multimodal Learning)是指处理和理解来自多个模态(如文本、图像、音频)的数据的过程。NLP与CV的融合是多模态学习的一个重要分支,它结合了文本理解和图像分析的能力,使计算机能够更全面地理解和解释现实世界的信息。 1.

By Ne0inhk
【AI 学习】解锁Claude Skills:开启AI应用新维度

【AI 学习】解锁Claude Skills:开启AI应用新维度

一、Claude Skills 是什么? 1.1 官方定义剖析 Claude Skills 是 Anthropic 公司为其人工智能模型 Claude 打造的一项创新性的功能扩展机制。从 Anthropic 的官方阐述来看,它本质上是一种标准化的、可复用的模块化系统,旨在赋予 Claude 执行特定领域复杂任务的能力 。通过 Claude Skills,用户能够让 Claude 迅速化身为专业领域的 “专家”,完成从常规的文本处理到复杂的业务流程自动化等多样化任务。 举例来说,在文档处理领域,以往使用普通的 AI 模型处理合同文档时,可能需要多次详细地输入指令,要求其提取关键条款、检查格式规范等,且每次处理都需重复这些指令,而借助 Claude Skills,用户只需创建一个专门用于合同处理的 Skill,将合同处理的流程、关键信息提取规则等内容封装其中,后续再处理合同时,Claude 就能自动调用该 Skill,

By Ne0inhk