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;//12
	return 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 == 10
	cout << *p << endl;//*p == 20
	return 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~

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

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

相关文章

数学知识——欧拉函数

数学知识&#xff08;二&#xff09; 20240628 求和N互质的个数公式 先分解N&#xff0c;再求个数fai n欧拉函数的证明&#xff1a;用容斥原理 不考 求质因子 p1, … , pk 1-N中与N互质的个数&#xff0c; 去掉质因子倍数 是pi的倍数的有N/pi个&#xff0c;但是会有既是p1也是…

计算机人说学校-南京大学-计算机方向

1. 专长、特点与特色 南京大学计算机专业在国内外享有很高的声誉&#xff0c;其专长、特点和特色主要体现在以下几个方面&#xff1a; 理论性强&#xff1a;重视数学、逻辑、数据结构、算法、电子设计、计算机体系结构和系统软件等方面的理论基础和专业技术基础。实践性强&am…

大厂10余年经验总结,用户研究领域入门标准书籍来了!

《用户研究方法&#xff1a;卓越产品和服务的用户研究技巧》一书近期出版&#xff0c;本书是用户研究领域入门标准书籍&#xff0c;是一本带你进入用户研究世界&#xff0c;通过研究用户让您工作更出色的书籍。 内容及特色 本书共 10 章&#xff0c;分为三篇。 第一篇&#xf…

Qt实现手动切换多种布局

引言 之前写了一个手动切换多个布局的程序&#xff0c;下面来记录一下。 程序运行效果如下&#xff1a; 示例 需求 通过点击程序界面上不同的布局按钮&#xff0c;使主工作区呈现出不同的页面布局&#xff0c;多个布局之间可以通过点击不同布局按钮切换。支持的最多的窗口…

鸿蒙应用更新跳转到应用市场

鸿蒙没有应用下载安装&#xff0c;只支持跳转到应用市场更新 gotoMarket(){try {const request: Want {parameters: {// 此处填入要加载的应用包名&#xff0c;例如&#xff1a; bundleName: "com.huawei.hmsapp.appgallery"bundleName: com.huawei.hmos.maps.app}}…

昇思25天学习打卡营第8天|模型训练

昇思25天学习打卡营第8天|模型训练 前言模型训练构建数据集定义神经网络模型定义超参、损失函数和优化器超参损失函数优化器 训练与评估 个人任务打卡&#xff08;读者请忽略&#xff09;个人理解与总结 前言 非常感谢华为昇思大模型平台和CSDN邀请体验昇思大模型&#xff01;从…

PFA滴定管带阀门耐酸碱本底值低

一、产品介绍 酸式滴定管为一细长的管状容器&#xff0c;一端具有活栓开关用来控制滴定的速度&#xff0c;其上具有刻度指示量度&#xff0c;是分析化学中常用的滴定仪器。可用于进行酸碱中和滴定试验等&#xff0c;量取对橡皮有侵蚀作用的液体。 我司生产的PFA酸式滴定管是用…

全球3DMAX插件界又更新了什么?

“3DMAX插件界”不这样称呼又叫他们什么呢&#xff1f;顾名思义就是开发3dmax插件的那个圈子。现在的3D类软件越来越多&#xff0c;但是&#xff0c;3dmax的地位仍然举足轻重。3dmax软件之所以受欢迎&#xff0c;不仅仅是因为自身的功能强大&#xff0c;还有其良好的可扩展性&a…

哪个麦克风音质好,麦克风哪种好,2024年热门家用麦克风推荐

​在这个信息爆炸的时代&#xff0c;网络直播和短视频成为了人们获取信息、娱乐和社交的重要方式。作为自媒体人&#xff0c;拥有一款优秀的领夹式无线麦克风是必不可少的。它不仅能够帮助你在各种环境中保持清晰的声音&#xff0c;还能提升你的作品质量和专业度。然而&#xf…

Parade接口芯片选型和应用,点击查看!

01 常见数据 / 媒体接口电路 接口电路是电子设备之间&#xff0c;电子设备与外围设备之间&#xff0c;电子设备内部部件之间起连接作用的逻辑电路&#xff0c;接口电路是设备处理器与外部设备进行信息交互的桥梁。 图1&#xff1a;常见高速数据/多媒体接口 1.1 USB接口 从最早…

思维模型:看透本质的思维框架,和它组合个个是王炸(非常详细)零基础入门到精通, 收藏这一篇就够了

为什么要从「为什么」开始&#xff1f; 如何想到又做到&#xff0c;提高行动力&#xff1f; 知行合一的途径&#xff1f;有用的工具&#xff1f; 剧透一下&#xff0c;读完本篇&#xff0c;你会收获一些王炸组合。 01 黄金思维圈 Why→How→What 黄金思维圈是西蒙斯涅克…

算法类学习笔记 ———— 车道线检测

文章目录 介绍基于传统计算机视觉地车道线检测基于道路特征的检测方法基于颜色特征的检测方法基于灰度特征的检测方法 基于彩色特征的检测方法基于纹理特征的检测方法基于多特征融合的检测方法 基于道路模型地检测方法直线模型曲线模型 基于深度学习的车道线检测LaneNet H-Net…

windows离线安装显卡驱动解决方案

前言 我们说这个离线泛指计算机无公网环境&#xff0c;而我们需要将显卡驱动打上&#xff0c;既然没有公网&#xff0c;我们就无法使用联网的方式&#xff08;傻瓜式安装&#xff09;&#xff0c;受各种原因限制&#xff0c;也不可以把主机搬走连上互联网进行安装。总之…

动手学深度学习(Pytorch版)代码实践 -计算机视觉-38实战Kaggle比赛:图像分类 (CIFAR-10)

38实战Kaggle比赛&#xff1a;图像分类 (CIFAR-10) 比赛链接&#xff1a;CIFAR-10 - Object Recognition in Images | Kaggle 导入包 import os import glob import pandas as pd import numpy as np import torch import torchvision from torch.utils.data import Dataset…

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

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

如何学好AI绘画?点这里有答案!

前言 地狱难度的求职模式下&#xff0c;“掌握一门技术”的那部分求职者&#xff0c;远比其他人更有竞争力&#xff1b;而拥有出色技术和技能的设计师、以及未来想做设计师的小伙伴们&#xff0c;怎么才能更好实现工作自由&#xff1f; 只有两个字&#xff1a;学习。 学习新…

【Go】excelize库实现excel导入导出封装(四),导出时自定义某一列或多列的单元格样式

大家好&#xff0c;这里是符华~ 查看前三篇&#xff1a; 【Go】excelize库实现excel导入导出封装&#xff08;一&#xff09;&#xff0c;自定义导出样式、隔行背景色、自适应行高、动态导出指定列、动态更改表头 【Go】excelize库实现excel导入导出封装&#xff08;二&…

uniapp运行到小程序Vue.use注册全局组件不起作用

真想吐槽一下小程序&#xff0c;uniapp运行到小程序使用Vue.use注册全局组件根本不起作用&#xff0c;也不报错&#xff0c;这只是其中一个问题&#xff0c;其他还有很多问题&#xff0c;比如vue中正常使用的没问题的语法&#xff0c;运行到小程序就不行&#xff0c;又是包太大…

第一后裔延迟高怎么办?快速降低第一后裔延迟

第一后裔/The First Descendant一款射击游戏&#xff0c;融合了刷宝、角色扮演、团队合作、剧情等元素&#xff0c;让每个玩家都能在自己的角度上&#xff0c;找到切入点&#xff0c;并不断地成长&#xff0c;一步步解开后裔身上隐藏的秘密。近期该作正式上线&#xff0c;很多玩…

如何选择适合您业务需求的多语言跨境电商系统源码

随着互联网技术的飞速发展和全球市场的日益融合&#xff0c;多语言跨境电商已经成为许多企业进军国际市场的重要战略。在这个竞争激烈的时代&#xff0c;拥有一个适合自己业务需求的多语言跨境电商系统源码至关重要。本篇文章将为您揭秘如何选择适合您业务需求的多语言跨境电商…