C++中的类型转换操作符:static_cast reinterpret_cast const_cast dynamic_cast

目录​​​​​​​

C语言中的类型转换

C++中的类型转换

C++中的类型转换操作符

static_cast

reinterpret_cast

const_cast

volatile关键字

赋值兼容

dynamic_cast


C语言中的类型转换

基本概念:赋值运算符左右两侧类型不同,或形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,需要发生类项转换,C语言中有两种形式的类型转换,隐式类型转换和显示类型转换

注意事项:有关联的类型才可以相互转换,小类型会转换为大类型

  1. 整型之间的隐转(int、long、short)
  2. 整型和浮点数间的隐转
  3. 整型和字符型间的隐转
  4. bool和整型、指针间的隐转(整数0和空指针均表示假)
  5. 整型和指针间的强转(地址的本质是一个编号所以可以)
//整型转换为指针
//缺点:在绝大多数情况下是不安全的,除非你确切知道这个整数表示的内存地址是有效的
int number = 1234;
int *ptr = (int *)number;//指针转换为整型:通常用于获取指针的内存地址
//缺点:如果在64位系统上,将指针转换为32位整数(如 int),可能会导致数据丢失。因此,建议使用 intptr_t 或 uintptr_t 类型,它们在 <stdint.h> 头文件中定义,可以确保适当的大小来存储指针值
int *ptr = &number;
int address = (int)ptr;

关于intptr_t和uintptr_t可以查看:intptr_t、uintptr_t数据类型的解析

  1. 不同类型的指针间的强转
//不同类型的指针间的强制类型转换
char s = 'a';
char* ptr1 = &s;
int* ptr2 = (int*) ptr1;

显示类型转换的缺点:

  • 可能导致数据丢失当从一个较大的数据类型转换为一个较小的数据类型时,可能会丢失数据。例如,将 double 转换为 int 时,小数部分会被截断
double d = 3.14; int i = (int)d; // i = 3, 小数部分丢失
  • 降低代码可读性频繁使用显式类型转换会使代码变得难以阅读和理解,尤其是当类型转换逻辑复杂时
float f = (float)((int)doubleValue * 2.0);
  • 增加错误风险进行类型转换时,容易忽略一些潜在的错误,如溢出或数据精度问题,导致难以发现的bug
long longValue = 1234567890123456789LL; 
int intValue = (int)longValue; // 可能会溢出

隐式类型转换的缺点:

  • 隐蔽的数据丢失int 转换为 float 时,如果整数的值超过了浮点数的精度范围,可能会丢失精度

int i = 123456789; float f = i; // 可能会丢失精度
  • 难以调试和维护隐式类型转换发生在幕后,可能导致意外的结果和难以调试的问题。出错时需要仔细检查代码,以确保所有隐式转换都符合预期

//int被转换为size_t,当传入的pos = 0时,会陷入死循环 
void Insert(size_t pos)
{int end = 10;// 比较的时候end会隐式类型转换成size_t,再比较while (end >= pos){cout << end << "挪走" << endl;--end;}
}

C++中的类型转换

基本概念:C++中通过构造函数和重载可以实现内置类型与自定义类型间、自定义类型间的转换

  • 内置类型->自定义类型:借助构造函数,隐式类型转换
//单参数的构造函数,支持内置类型隐式转换成自定义类型
string s1 = "111111";
const string& s2 = "11111";
  • 自定义类型->内置类型:重载某个类型(operator +类型名)
class A
{
public:operator int(){return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};int main()
{A aa;int a = aa;int b = (int)aa;cout << a << endl;cout << b << endl;return 0;
}

  • 自定义类型->自定义类型:借助构造函数进行隐式类型转换(initializer_list和容器间)

C++中的类型转换操作符

基本概念:C++依然兼容C语言的两种类型转换方式,但是为了加强类型转换时的可视性,C++引入了四种类型转换操作符,它们是一些进行类型转换时的命名建议,并不强制

static_cast

基本概念:进行有关联的类型间的隐式类型转换(编译时进行,也叫静态转换)

int main()
{//C++的隐式类型转换:明显double d = 12.34;int a1 = static_cast<int>(d);cout << a1 << endl;//12//C语言的隐式类型转换:不明显int a2 = d;cout << a2 << endl;//12return 0;
}

reinterpret_cast

音标:riːɪnˈtɜːrprət

基本概念:进行强制类型转换,不进行类型检查

int main()
{int a = 12;// int* p = static_cast<int*>(a); 报错,int和int*不是两个相关的类型int* p = reinterpret_cast<int*>(a);cout << p << endl;return 0;
}

const_cast

基本概念:删除对象的const属性

int main()
{const int a = 10;int* p = const_cast<int*>(&a); // 去除const属性*p = 20; // 尝试修改值cout << a << endl;//a == 10cout << *p << endl;//*p == 20return 0;
}

        对比监视列表和控制台,可以发现虽然在内存中a的值变为了20,但是打印时a仍为原来的10,这是因为编译器知道const修饰的变量不会被修改,那么编译器在编译阶段就会对其优化,即编译器会将常量的值直接内联到使用该常量的地方,而不是每次都访问内存中的存储位置,这一优化技术称为“常量折叠”或“常量传播

补充:const修饰的局部变量仍然存放在栈上,修饰的全局变量才放在常量区中

volatile关键字

基本概念:用于指示编译器不对变量进行优化(带入上述代码再试一试即可)

volatile const int a = 10;//表示不会对a进行优化

结论:const_cast和reinterpret_cast都是强制类型转换(const_cast的第一个例子中的a去掉const修饰也能const_cast也能正常使用,且a打印时也为20),但是单独将const_cast拿出来就是因为可能出现因为编译器对const修饰的变量进行优化而导致的内存可见性

赋值兼容

基本概念:有继承关系的派生类与基类之间所遵循的赋值规则,包括向上和向下转型

  • 向上转型:派生类对象赋值给基类对象(发生切片,切片  != 类型转换)、派生类的指针/引用赋值给基类的指针/引用(通常情况下都支持)(即这两种情况正常情况下都是可以支持的
#include <iostream>
using namespace std;class A
{};class B : public A
{};int main()
{//向上转型B bb;A aa = bb;//派生类对象直接赋值给基类对象,发生切片A* ptr = &bb;//派生类对象的指针可以直接赋值给基类对象的指针B& cc = bb;A& str = cc;//派生类对象的引用可以直接赋值给基类对象的引用return 0;
}
  • 向下转型:基类对象赋值给派生类对象(除非有相关的构造函数、否则即使是强转也转不了)、基类对象的指针/引用赋值给派生类对象的指针/引用(可以通过强转实现,但有越界风险需要得到控制)

//有相应的构造函数才能实现基类对象到派生类对象间的转换
#include <iostream>
using namespace std;class A {
public:int baseData;A() : baseData(0) {}A(int data) : baseData(data) {}
};class B : public A {
public:B() {};// 自定义构造函数,实现基类到派生类的转换B(const A& a) : A(a) {cout << "hello" << endl;}// 自定义赋值运算符,实现基类到派生类的转换B& operator=(const A& a) {cout << "world" << endl;return *this;}
};int main() {A aaa(10);B bbb;bbb = aaa;  // 使用自定义赋值运算符B bbb2 = aaa;  // 使用自定义构造函数return 0;
}

dynamic_cast

基本概念:为了能控制向下转型时的越界问题、C++提供了dynamic_cast类型转换操作符,dynamic_cast会在转换前检查是否能转换成功,可以转换就转换、不能转换就返回0

#include <iostream>
using namespace std;class A
{
public:virtual void f() {}int _a = 0;
};class B : public A
{
public:int _b = 1;
};void fun(A* pa)
{// 向下转换:父->子// pa指向子类对象,转回子类,是安全的// pa指向父类对象,转回子类,是不安全的,存在越界的风险问题// 不安全//B* pb = (B*)pa;//  pa指向子类对象,转回子类,正常转换//  pa指向父类对象,转回子类,转换失败B* pb = dynamic_cast<B*>(pa);if (pb){cout << pb << endl;cout << pb->_a << endl;cout << pb->_b << endl;}else{cout << "转换失败" << endl;}
}int main()
{A a;B b;fun(&a);//父类转为子类fun(&b);//子类转为子类return 0;
}

注意事项:dynamic_cast在使用时,基类要有虚函数(有就行)

~over~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在宝塔面板中配置SSL证书?

目录 一、申请证书二、登录宝塔面板配置SSL证书一、申请证书 登录华为云,进入“云证书管理服务 CCM”: 点击“购买证书”: 选择“DV(Basic)”->“DigiCert”,点击【立即购买】购买有效期为3个月的免费证书。 申请证书:

JAVA里的object类

public static String toString(Object o) // 获取对象的字符串表现形式 public static boolean equals(Object a, Object b) // 比较两个对象是否相等 public static boolean isNull(Object obj) // 判断对象是否为null pu…

基于单片机的 LED 照明灯智能调光系统设计

摘  要&#xff1a; 社会经济的不断发展&#xff0c;推动了智能化生活的进程&#xff0c;智能调光技术开始广泛应用在生活中&#xff0c;人们也逐渐提高了灯光亮灯率等的要求。基于此&#xff0c;笔者主要设计了基于单片机的 LED 照明灯智能调光系统&#xff0c;希望能够为相关…

骨传导耳机哪个牌子好?精选靠谱好用的TOP5骨传导耳机推荐!

在超过八成的音乐爱好者都面临听力健康问题的当下&#xff0c;骨传导耳机因其独特的听觉体验和对听力的保护&#xff0c;在音频设备市场中备受瞩目。但近期我发现不少用户在选购骨传导耳机时常常受到不专业产品的误导。身为有着5年经验的数码博主&#xff0c;在此提醒大家&…

老师怎样用微信发布期末成绩

老师们&#xff0c;期末季又到了&#xff0c;还在为如何发布成绩而头疼&#xff1f;今天&#xff0c;就让我来分享一些小技巧&#xff0c;让你们在微信上发布成绩更加高效&#xff0c;同时又能保护学生的隐私。 首先&#xff0c;我们要确保成绩的安全性和隐私性。在微信上&…

数据恢复篇:如何在 Android 手机上恢复未保存/删除的 Word 文档

在 Android 手机上访问 Word 文档通常很简单&#xff0c;但是当这些重要文件被删除或未保存时会发生什么&#xff1f;这种情况虽然令人痛苦&#xff0c;但并非毫无希望。到 2024 年&#xff0c;有几种强大的方法来处理此类数据丢失。本指南重点介绍如何在Android手机上恢复已删…

Python | Leetcode Python题解之第208题实现Trie(前缀树)

题目&#xff1a; 题解&#xff1a; class Trie:def __init__(self):self.children [None] * 26self.isEnd Falsedef searchPrefix(self, prefix: str) -> "Trie":node selffor ch in prefix:ch ord(ch) - ord("a")if not node.children[ch]:retur…

2008-2022年款哈弗维修手册和电路图线路图接线图资料更新

经过整理&#xff0c;2005-2022年款长城哈弗全系列已经更新至汽修帮手资料库内&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照…

word怎么转换成pdf?分享3种PDF文件转换技巧

word怎么转换成pdf&#xff1f;在日常办公中&#xff0c;将Word转换成PDF可以带来诸多便利。首先&#xff0c;PDF格式具有跨平台的通用性&#xff0c;无论在哪个操作系统或设备上&#xff0c;都能保持文档的原始布局和格式。其次&#xff0c;PDF文件不容易被篡改&#xff0c;可…

【Unity】 HTFramework框架(五十二)使用 HybridCLR 热更新

更新日期&#xff1a;2024年7月1日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 HybridCLR 热更新一、启用宏定义二、导入HybridCLR三、设置热更新程序集四、资源、代码热更 HybridCLR 热更新 HybridCLR是一个特性完整、零成本、高性能…

Mac多线程下载管理器:Neat Download Manage 最新版

Neat Download Manager&#xff08;NDM&#xff09;是一款功能强大的下载管理软件&#xff0c;它可以帮助用户更有效地管理和下载网络资源。这款软件支持多种浏览器和协议&#xff0c;可以提升下载速度&#xff0c;恢复中断的下载任务&#xff0c;以及自动化下载过程。在使用任…

如何设置农历日程提醒 农历提醒小妙招

在中国&#xff0c;农历仍然承载着深厚的文化传统和民俗意义。无论是庆祝传统节日&#xff0c;还是纪念亲朋的生日&#xff0c;农历日期都显得格外重要。然而&#xff0c;随着生活节奏的加快&#xff0c;我们有时会因忙碌而遗忘这些特殊的日子。这时&#xff0c;一个能够准确提…

游戏AI的创造思路-技术基础-关于艾宾浩斯遗忘曲线的迷思

对于艾宾浩斯遗忘曲线和函数&#xff0c;我一直都有小小的迷思&#xff0c;总想实验下用艾宾浩斯函数来替换sigmoid函数作为激活函数&#xff0c;打造更接近人类的AI算法&#xff0c;这篇文章旨在讨论下 目录 3.10. 艾宾浩斯曲线 3.10.1. 定义 3.10.1.1. 曲线计算公式 3.10…

干货分享:Spring中经常使用的工具类(提示开发效率)

环境&#xff1a;Spring5.3…30 1、资源工具类 ResourceUtils将资源位置解析为文件系统中的文件的实用方法。 读取classpath下文件 File file ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX "logback.xml") ; // ...读取文件系统文件 file Resou…

【刷题汇总--数字统计、两个数组的交集、点击消除(栈)】

C日常刷题积累 今日刷题汇总 - day0011、数字统计1.1、题目1.2、思路1.3、程序实现 2、两个数组的交集2.1、题目2.2、思路2.3、程序实现 3、点击消除(栈)3.1、题目3.2、思路3.3、程序实现 今日刷题汇总 - day001 1、数字统计 1.1、题目 请统计某个给定范围[L, R]的所有整数中…

百事可乐推出具有视频屏幕和人工智能技术的智能罐头

在最近于法国戛纳举行的国际创意节上&#xff0c;百事公司推出了创新的智能罐头。这些罐头不同于传统产品&#xff0c;它们采用了环绕式3D屏幕&#xff0c;能够展示高清视频内容&#xff0c;为品牌宣传和促销带来了全新的视角。经过两年多的精心研发&#xff0c;这些智能罐成为…

LLM原生开发路线图指南

引言 大型语言模型&#xff08;LLM&#xff09;正在迅速成为现代人工智能的基石。然而&#xff0c;目前还没有出现公认的最佳实践&#xff0c;而且先驱们往往没有明确的开发路线图。因此&#xff0c;这种状况急需要有人重新发明有关轮子&#xff1b;否则&#xff0c;将会使人陷…

spring中集成mybatis,并测试是否成功

首先你要配置pom.xml <!-- 连接 MySQL 数据库的驱动程序 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><!-- spring-jdbc -->&…

Advanced slides插件无法预览幻灯片

advanced-slides的官方地址&#xff1a; MSzturc/obsidian-advanced-slides: Create markdown-based reveal.js presentations in Obsidian (github.com) 官方教程和文档&#xff1a; Advanced Slides Documentation (mszturc.github.io) 中文版也有博客翻译了&#xff1a;Ob…

软考中级系统集成项目管理工程师备考笔记

目录 一&#xff0c;通用内容 &#xff08;一&#xff09;信息与信息化 1.1&#xff0c;信息 信息基本概念 信息的传输模型 信息的质量属性 1.2&#xff0c;信息系统 信息系统的基本概念 信息系统定义 信息系统集成 1.3&#xff0c;信息化 信息化层次 信息化的核心…