c++学习笔记(6)-类型转换

1、概念

C++类型转换是将一种数据类型转换为另一种数据类型的过程。

2、分类

C++中的类型转换可以从3个角度来划分:

  • 根据类型转换是由程序员显式指定,还是由编译器自动完成,分为显式类型转换和隐式类型转换;
  • 根据参与类型转换的变量类型,分为标准类型转换和用户定义类型转换;
  • 根据类型转换的运算规则,分为按照存储值转换和按照数值转换。

2.1、显式和隐式类型转换

image.png
下面是显式类型转换和隐式类型转换的例子:
1、显式类型转换,在下面的代码中,变量b是double类型,使用显式类型转换将其转换为int类型,并将结果赋值给变量c。

 // 将double类型的变量b转换为int类型
double b = 3.14; 
int c = (int)b;

2、隐式类型转换,在下面的代码中,变量a是int类型,变量b是double类型,当它们参与除法运算时,系统会自动将变量a转换成double类型,使得运算结果也是double类型。这就是隐式类型转换。

// 变量a会被隐式转换为double类型,然后进行除法运算
int a = 5;
double b = 3.14; 
double c = a / b; 

2.2、标准类型转换和用户定义类型转换

标准类型转换指C++ 基本类型之间的转换,可以概括为以下几类:

  • 数值、字符、bool、枚举类型之间的转换;
  • 指针类型之间、引用类型之间的转换;
  • 限定符的添加和删除:比如const,volatile。

用户定义类型转换指类类型与基本类型、或者类类型之间的转换。用户定义类型转换,需要程序员实现以下两种成员函数:

  • 转换构造函数:定义在类中的一种特殊的构造函数,它可以将其它类型转换为该类的一个对象。
  • 类类型转换操作符:定义在类中的一种特殊的成员函数,它可以将一个对象转换为另一个基本类型。

举个例子:

//重载int运算符,把Object转化为int类型
class Object{
public:
    //转换构造函数
    Object(int num)m_number(num){}
    //类类型转换操作符:定义int运算符
    operator int(){return number;}
private:
    int m_number;
};

int main() {
    int number = 2;
    Object obj = number;//把int类型转换为Object类型
    int newNumber = (int)obj;//把Object类型转换为int类型
    return 0;
}

2.3、按照存储值转换和按照数值转换

按照存储值转换通常是指在某些情况下进行数据类型的强制转换,这种转换是按照字符在计算机中存放的二进制值进行转换的,包括:int、short、char、bool、void、指针类型、signed和unsigned类型之间的转换。
按照数值转换通常是针对数值类型进行的,这种转换是按照数值大小进行等值转换,包括:浮点数类型和非浮点数类型之间的转换,比如double和int之间的转换。

3、指针类型转换

C++提供了4种运算符,用于指针(引用)类型转换,4种运算符号的区别如下:
image.png
虽然说上述运算符号还可用于把指针类型转换为非指针类型,但应用场景少,不考虑。

3.1、reinterpret_cast

reinterpret_cast用于任意指针(引用)类型之间的转换。转换运算过程中,只是简单地把源变量的二进制值拷贝到新的类型变量中,不作任何类型检查。例如,对于以下代码:

int main() {
    int* p1 = new int(10);
    char* p2 = reinterpret_cast<char*>(p1);
    std::cout << *p1 << std::endl;  // 输出10
    std::cout << *p2 << std::endl;  // 输出未定义的值
    return 0;
}

在这个例子中,将一个int类型的指针p1转换为了char类型的指针p2,虽然可以取得p2所指向的地址,但是由于reinterpret_cast忽略了指针类型所指向的对象类型,因此输出的值是未定义的。因此,在使用reinterpret_cast时,需要非常小心和谨慎。

3.2、static_cast

static_cast用于子类指针(引用)和父类指针(引用)之间的相互转换,在编译期执行类型检查。在C++中,使用static_cast将基类指针转换为子类指针是一种常见的操作,但是在实际使用时,可能会出现以下错误,假设我们有如下的类层次结构:

class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {
public:
    int data;
};

我们创建一个Base类的指针,并将其指向基类对象:

Base* basePtr = new Base;

此时,如果试图使用static_cast将basePtr指针转换为Derived指针类型,会导致编译时不会发现错误,但是在运行时则会产生未定义行为,例如:

Derived* derivedPtr = static_cast<Derived*>(basePtr);
int data = derivedPtr->data;

这是因为类型转换时,将一个指向基类对象的指针转换为子类指针,但由于子类对象不存在,所以在使用子指针访问子类成员时会发生未定义行为。

3.3、dynamic_cast

dynamic_cast用于子类指针(引用)和父类指针(引用)之间的相互转换,在运行时进行类型检查。当用户试图使用dynamic_cast将基指针转换为子类指针类型,如果子类对象不存在,那么会返回nullptr。
使用dynamic_cast进行类型转换,并检查返回的指针是否为nullptr,就可以解决上述例子中static_cast引起的错误:

Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
if (derivedPtr) {
    int data = derivedPtr->data;
} else {
    std::cout << "转换失败" << std::endl;
}

3.4、const_cast

const_cast是C++中用于取消指针或引用对象的const限定符的一种操作符,它用于将const类型转换为非const类型。const_cast的学习难点在于理解它的使用场景,如果我们要把const类型转换为非const类型,为什么不一开始就把类型声明为const类型呢?这是因为const类型数据可能是第三方库定义的,当我们希望在不修改第三方库的源码的情况下,修改const数据,需要用到该运算符。

4、总结

类型转换在程序中具有重要的作用和意义,但在使用过程中需要注意类型转换的安全性,主要有以下两个方面:

  • 类型转换合法性。在进行类型转换时,需要保证转换的数据类型是合法的,例如不要把指针类型转换为字符类型,没有任何意义。
  • 精度损失和溢出问题。在进行类型转换时,需要考虑数据类型的精度,在某些情况下,类型转换可能会导致精度损失,例如将浮点数转换为整数时,小数部分会被截断,可能会导致精度丢失。另外,在一些情况下,类型转换也可能会导致数据溢出,例如将一个很大的整数转换为一个较小的整数类型,将导致数据溢出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/272492.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于减法平均算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于减法平均算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于减法平均算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.减法平均算法4.实验参数设定5.算法结果6.…

测试用例要如何写

​ &#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试…

IDEA基本设置

本博客适用于纯新手小白&#xff0c;或者刚下载IDEA想要优化开发添加配置的读者。 基础设置 不区分大小写代码补全 打开 IntelliJ IDEA。转到 “File”&#xff08;文件&#xff09; > “Settings”&#xff08;设置&#xff09;&#xff08;Windows/Linux&#xff09;或 “…

swagger1.2 apiPost工具测试接口没有问题,换成swagger 接口调测时报错 Required request body is missing

把 请求方法由get换成post GetMapping换成 PostMapping 原因apiPost自动把请求json参数封装到请求体里了&#xff0c; 但swagger没有封装&#xff0c;通过networker可以看到载荷里并没有任何东西

(C++)DS哈希查找—二次探测再散列(附思路和详细注释)

Description 定义哈希函数为H(key) key%11。输入表长&#xff08;大于、等于11&#xff09;&#xff0c;输入关键字集合&#xff0c;用二次探测再散列构建哈希表&#xff0c;并查找给定关键字。 Input 测试数据组数 1≤&#xfffd;≤50. 每组测试数据格式如下&#xff1a…

面试题:Zabbix 和 Prometheus 到底怎么选?

文章目录 前言历史简介PrometheusZabbix 架构对比PrometheusZabbix 综合对比总结 前言 新公司要上监控&#xff0c;面试提到了 Prometheus 是公司需要的监控解决方案&#xff0c;我当然是选择跟风了。 之前主要做的是 Zabbix&#xff0c;既然公司需要 Prometheus&#xff0c;…

【如何破坏单例模式(详解)】

✅如何破坏单例模式 &#x1f4a1;典型解析✅拓展知识仓✅反射破坏单例✅反序列化破坏单例✅ObjectlnputStream ✅总结✅如何避免单例被破坏✅ 避免反射破坏单例✅ 避免反序列化破坏单例 &#x1f4a1;典型解析 单例模式主要是通过把一个类的构造方法私有化&#xff0c;来避免重…

鸿蒙系统的分布式技术:重塑智能终端的未来

华为鸿蒙系统自发布以来&#xff0c;凭借其创新的分布式技术&#xff0c;改变了我们对智能终端的认知和使用方式。鸿蒙系统的分布式技术是一种全新的设计理念&#xff0c;它将不同设备、不同应用场景视为一个整体&#xff0c;通过共享、协同和无缝连接&#xff0c;为用户带来前…

android setText不生效问题

1.直接说解决方案&#xff1a; 在代码没问题的情况下&#xff0c;将你的TextView的Id改一下&#xff0c;然后再重启编译器即可(注意&#xff0c;不修改TextView的ID&#xff0c;单独重启是没有作用的&#xff01;) 2.出现问题的过程&#xff1a; 产品新增一个需求&#xff0c…

SpringBoot整合JWT+Spring Security+Redis实现登录拦截(一)登录认证

一、JWT简介 JWT 全称 JSON Web Token&#xff0c;JWT 主要用于用户登录鉴权&#xff0c;当用户登录之后&#xff0c;返回给前端一个Token&#xff0c;之后用户利用Token进行信息交互。 除了JWT认证之外&#xff0c;比较传统的还有Session认证&#xff0c;如何选择可以查看之前…

MAGVIT: Masked Generative Video Transformer

Paper name MAGVIT: Masked Generative Video Transformer Paper Reading Note Paper URL: https://arxiv.org/abs/2212.05199 Project URL: https://magvit.cs.cmu.edu/ Code URL: https://github.com/google-research/magvit TL;DR 2023 年 CMU、google 等发表 CVPR20…

[Python工程化之路] 搭建Python开发环境 包管理环境以及Linter

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 在工程化上,Python相比于Java,C#这类语言还是差了不少,不过整个生态还是不错的. 项目结构 一般有两种,一种称为flat另一种为src. ├── sample │ ├── AUTHORS.rst │ ├── docs | | ├── conf.py │ │ └…

深入Apache Commons Config:管理和使用配置文件

第1章&#xff1a;引言 咱们都知道&#xff0c;在软件开发中&#xff0c;管理配置文件是一件既重要又让人头疼的事。想象一下&#xff0c;咱们的应用程序有一堆设置需要调整&#xff0c;比如数据库的连接信息、应用的端口号&#xff0c;或者是一些功能的开关。如果这些信息硬编…

java实现广度优先搜索算法

广度优先搜索算法&#xff08;BFS&#xff09;是一种用于图遍历的算法。它从图的某个节点开始&#xff0c;依次访问其所有邻接节点&#xff0c;再依次访问邻接节点的邻接节点&#xff0c;以此类推&#xff0c;直到遍历完所有节点。 BFS使用队列数据结构来实现遍历过程。具体步…

关于 Appium 各种版本的安装,都在这里

大家在初次接触 Appium 时会看到网上各种帖子讲解如何安装 Appium&#xff0c;各种 Appium 版本的安装教程满天飞&#xff0c;而很多帖子中提供的安装教程是已经过时了的&#xff0c;容易误导初学者。 这篇文章带着你一起全面了解 Appium 各种版本如何选择如何安装。 一句话概述…

Superset 二次开发之自定义Viz Plugins(Hello World v2)

环境&#xff1a; Node.js 16npm 7 or 8安装webpack 全局安装 npm install webpack -g 安装eslint superset-frontend> npm install eslint 1.Yeoman 生成器 全局安装Yo> npm i -g yo 2.进入/superset-frontend/packages/generator-superset目录 npm i && npm…

传感器原理与应用--传感器基本特性与应变式传感器

文章目录 上一篇传感器的基本特性应变式传感器应变式传感器的应用下一篇 上一篇 传感器的基本特性 一般来说能把特定被测量信息按一定规律转换成某种可用信号的器件或装置&#xff0c;称为传感器 静态特性 灵敏度 定义&#xff1a;输出量增量 Δ y \Delta y Δy与引起输出量…

xstream 远程代码执行 CVE-2021-29505 已亲自复现

xstream 远程代码执行 CVE-2021-29505 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 XStream 是用于将 Java 对象序列化为 XML 并再次序列化的软件。 1.4.17 之前的 XStream 版本中存在一个漏洞&#xff0c;可能允许远程攻…

集成钉钉机器人消息推送

一、简介 背景 客户需要通过钉钉接收消息通知 名词解释 群聊机器人&#xff1a;钉钉群里可以创建一个机器人&#xff0c;平台通过机器人把告警/通知推送到群里私聊机器人&#xff1a;钉钉后台开启机器人配置&#xff0c;平台绑定此机器人后&#xff0c;可以通过私聊的方式将…

C/S医院检验LIS系统源码

一、检验科LIS系统概述&#xff1a; LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化&#xff0c;检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后&#xff0c;自动生成打印报告&#xff0c;通过网络存储在数据库中&#xff…