【C++】告别“类型转换”踩坑,从基础到四种核心强制转换方式

【C++】告别“类型转换”踩坑,从基础到四种核心强制转换方式

各位大佬好,我是落羽!一个坚持不断学习进步的学生。
如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步!
也欢迎关注我的blog主页:
落羽的落羽

文章目录

一、回顾C语言的类型转换

C语言的类型转换主要是隐式类型转换和强制类型转换:

  • 隐式类型转换,是编译器在特定情况下自动进行的类型转换,通常发生在不同类型的表达式运算中。主要是整型之间、整型与浮点型之间、浮点型之间的转换。
int a =1;double b =2.234; a = b;
  • 强制类型转换:是我们通过显式语法手动指定的类型转换,主要是整型和指针、指针和指针之间的转换。
int a =1;char* p =(char*)a;int* p1 =(int*)malloc(sizeof(int));

但是,并非所有类型直接都能转换。例如double就无法转为指针类型。

在这里插入图片描述

二、C++中的类型转换

1. 内置类型转为自定义类型

随着自定义类型的广泛使用,C++也支持了内置类型和自定义类型之间的相互转换:

  • 内置类型转换为自定义类型,需要自定义类型的相关构造函数支持。非常好理解,用内置类型转换为自定义对象,就相当于构造一个自定义对象。
classA{public:A(int a):a1(a),a2(a){}private:int a1;int a2;};
在这里插入图片描述

而当构造函数前加上关键字explicit,可以使这个构造函数不支持隐式类型转换。这就是之前我们学习智能指针时构造函数加了它的原因,我们不希望一个普通指针悄悄转换为智能指针。不过,还是支持强制类型转换的

在这里插入图片描述

2. 自定义类型转为内置类型

一个自定义类型对象想要转换为内置类型,需要内部重载operator()。这里不是常规的运算符重载,和仿函数中重载operator()的写法也不一样。它的用法是operator 类型(){...}(也可以加explicit修饰),转换的方式是函数体内自定义的,举个例子:

classA{public:A(int a):a1(a),a2(a){}operatorint(){return a1 + a2;}private:int a1;int a2;};
在这里插入图片描述

智能指针中,关于向bool类型的转换,就是这样写的:

在这里插入图片描述

3. 自定义类型之间的转换

自定义类型之间的转换,也是需要有相关的构造函数,很好理解,不再赘述。

4. 类型安全与C++的四种强制类型转换方式

4.1 什么是类型安全?

类型安全是指,编程语言在编译和运行时提供保护机制,避免非法的类型转换和操作,导致出现内存访问错误等,从而减少程序运行时的错误。

C语言不是类型安全的语言, 因为C语言允许隐式类型转换,一些特殊情况下就会导致越界访问的内存错误。不合理的使用强制类型转换也会导致问题,比如一个int*的指针强转成 double*的话,访问就会出现越界。
C++兼容C语言,也支持隐式类型转换和强制类型转换,它也不是类型安全的语言。因此,C++提出了四个显示强制类型转换 操作符static_cast / reinterpret_cast / const_cast / dynamic_cast,就是为了让类型转换相对而言更安全。

4.2 static_cast

static_cast用于两个意义相近的类型之间的转换,比如整型之间、整型和浮点型之间、普通类型和其引用类型之间等。

double a =1.234;int b =static_cast<int>(a);float c =static_cast<float>(b);int&& d =static_cast<int&&>(b);

4.3 reinterpret_cast

reinterpret_cast用于底层的类型转换,比如将一种类型的指针/引用直接转换为另一种类型。这种类型的转换后,对于内存的访问方式就会改变了,因此使用时需要很谨慎,自己要清楚明白使用后是否会出现问题。

int a =1;int* p1 =&a;char* p2 =reinterpret_cast<char*>(p1);

4.4 const_cast

const_cast用于const对象向非const对象的转换,会去掉const属性,使用时同样需要谨慎。

在这里插入图片描述

4.5 dynamic_cast

dynamic_cast主要用于多态类型之间的转换,尤其是用于基类指针/引用向派生类指针/引用的转换,因为派生类的指针/引用向基类指针/引用的转换是天然支持的(也就是切片)。
但是,它不是简单基类转换为派生类。一个基类的指针/引用,它可能指向的是一个基类的对象,也可能指向的是一个派生类对象的切片。dynamic_cast只能作用在后者,只有这个基类指针/引用指向的是派生类对象的切片,才能完成转换。对于前者情况,就不能转换,如果是基类指针指向基类,转换失败返回nullptr,如果是基类引用指向基类,转换失败抛出bad_cast异常

dynamic_cast还要求基类必须是多态类型,也就是必须有虚函数,因为它的运行时通过虚表中存储的type_info来判断一个基类指针/引用指向的是基类对象还是派生类对象。

classA{public:virtualvoidfunc(){}};classB:publicA{};
在这里插入图片描述

本篇完,感谢阅读

Read more

SpringBoot 整合 Langchain4j 实现会话记忆存储深度解析

SpringBoot 整合 Langchain4j 实现会话记忆存储深度解析

目录 一、前言 二、AI大模型会话记忆介绍 2.1 AI 大模型的会话记忆是什么 2.2 AI 大模型为什么需要会话记忆 2.3 AI 大模型会话记忆常用实现方案 2.4 LangChain4j 会话记忆介绍 2.4.1 LangChain4j 会话记忆介绍 2.4.2 LangChain4j 会话记忆类型 三、Langchain4j 会话记忆操作案例使用 3.1 前置准备 3.1.1 导入依赖文件 3.1.2 添加配置文件 3.1.3 前置案例 3.

By Ne0inhk
Spring Boot 数据访问与数据库集成

Spring Boot 数据访问与数据库集成

Spring Boot 数据访问与数据库集成 18.1 学习目标与重点提示 学习目标:掌握Spring Boot数据访问与数据库集成的核心概念与使用方法,包括Spring Boot数据访问的基本方法、Spring Boot与MySQL的集成、Spring Boot与H2的集成、Spring Boot与MyBatis的集成、Spring Boot与JPA的集成、Spring Boot的事务管理、Spring Boot的实际应用场景,学会在实际开发中处理数据库访问问题。 重点:Spring Boot数据访问的基本方法、Spring Boot与MySQL的集成、Spring Boot与H2的集成、Spring Boot与MyBatis的集成、Spring Boot与JPA的集成、Spring Boot的事务管理、Spring Boot的实际应用场景。 18.2 Spring Boot数据访问概述 Spring Boot数据访问是指使用Spring Boot进行数据库操作的方法。 18.2.1 数据访问的定义

By Ne0inhk
实战:Spring Boot 2.7.8 原生 SSE 服务端开发

实战:Spring Boot 2.7.8 原生 SSE 服务端开发

目录 前言 一、SSE知识简介 1、SSE是什么 2、SSE工作原理 3、SSE适用场景 二、SpringBoot中SSE的实现 1、Maven中引入 2、SSE服务类实现 3、SSE控制器类实现 4、最简单页面实现 三、成果展示 1、SSE连接 2、群发消息 3、点对点消息 四、总结 前言         在当今的互联网应用开发中,实时数据交互的需求日益增长。无论是股票交易系统中实时更新的股价信息,还是社交平台上的即时消息推送,亦或是物联网场景下传感器数据的实时传输,都对后端服务提出了更高的要求。传统的轮询机制虽然简单,但效率低下且资源消耗大;而WebSocket虽然功能强大,但在某些场景下显得过于复杂且实现成本较高。在这种背景下,Server-Sent Events(SSE)作为一种轻量级的、基于HTTP协议的单向实时通信技术,逐渐受到开发者的关注。         SSE允许服务器主动向客户端推送数据,而无需客户端频繁发起请求,

By Ne0inhk