Cpp::静态 动态的类型转换全解析(36)

文章目录

  • 前言
  • 一、C语言中的类型转换
  • 二、为什么C++会有四种类型转换?
    • 内置类型 -> 自定义类型
    • 自定义类型 -> 内置类型
    • 自定义类型 -> 自定义类型
    • 隐式类型转换的坑
  • 三、C++强制类型转换
    • static_cast
    • reinterpret_cast
    • const_cast
    • dynamic_cast
  • 四、RTTI
  • 总结


前言

  Hello,学完这个,再看看 IO 流,我们的C++学习之路可能真的要结束了~


一、C语言中的类型转换

  在学习C++之前,不妨我们先看看C的类型转换的机制:

  在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化

  C语言中总共有两种形式的类型转换:隐式类型转换(整型之间 整型浮点数之间) 和 显式类型转换(指针之间 整型指针之间)

没有关联的类型不支持转换

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败。
  2. 显式类型转化:需要用户自己处理。
#include<iostream>
using namespace std;int main()
{int i = 1;// 隐式类型转换double d = i;printf("%d, %.2f\n", i, d);int* p = &i;// 显示的强制类型转换int address = (int)p;printf("%p, %d\n", p, address);// “类型强制转换”: 无法从“int *”转换为“double”// double x = (double)p;// 没有关联的类型不支持转换return 0;
}

二、为什么C++会有四种类型转换?

  C风格的转换格式很简单,但是有不少缺点的:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

  C++除了兼容C的转换用法之外还有三种转换方式:内置类型 -> 自定义类型 ;自定义类型 -> 内置类型 ; 自定义类型 -> 自定义类型

内置类型 -> 自定义类型

  内置类型转换为自定义类型通过 隐式类型转换 + 对应的构造函数 就能够实现

class A
{
public:A(int a1):_a1(a1){}A(int a1, int a2):_a1(a1),_a2(a2){}
private:int _a1 = 1;int _a2 = 1;
};int main()
{// 内置类型 -> 自定义类型A aa1 = 1;// 单参数隐式类型转换A aa2 = { 1,2 };// 多参数隐式类型转换,使用{}// A aa3 = { 1,2,3 };// 没有实现3个参数的构造函数或者initializer_list,就不能隐式类型转换return 0;
}

在这里插入图片描述

自定义类型 -> 内置类型

  自定义类型转化为内置类型,直接写不支持,需要写重载函数

class A
{
public:A(int a1):_a1(a1){}// 自定义类 -> 内置类型 重载函数operator int(){return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 1;
};int main()
{// 内置类型 -> 自定义类型A aa1 = 1;// 自定义类型 -> 内置类型 直接写不支持,需要重载int x = aa1;cout << x << endl;return 0;
}

在这里插入图片描述

自定义类型 -> 自定义类型

  自定义类型转换为自定义类型,直接写不支持,需要加拷贝构造

class A
{
public:A(int a1):_a1(a1){}// 成员变量私有,类外不能获取,const对象需要加constint get() const{return _a1;}
private:int _a1 = 1;int _a2 = 1;
};class B
{
public:B(const A& aa):_b1(aa.get()){}
private:int _b1;
};int main()
{// 内置类型 -> 自定义类型A aa1 = 1;// 自定义类型 -> 自定义类型 直接写不支持,需要加拷贝构造B bb = aa1;return 0;
}

在这里插入图片描述

隐式类型转换的坑

// 隐式类型转换的坑
void Insert(size_t pos)
{int end = 10;while (end >= pos){cout << end << endl;--end;}
}int main()
{Insert(5);// 插入0就有坑,-1转换为无符号整数为最大值Insert(0);return 0;
}

在这里插入图片描述

三、C++强制类型转换

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

static_cast、reinterpret_cast、const_cast、dynamic_cast

static_cast

  static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast

一样的,但它不能用于两个不相关的类型进行转换

int main()
{int i = 1;// 隐式类型转换 : static_castdouble d = static_cast<double>(i);cout << d << endl;// 强制类型转换int* p = &i;//int address = static_cast<int>(p);//printf("%p %d\n", p, address);return 0;
}

在这里插入图片描述

class A
{
public:A(int a1):_a1(a1){}
private:int _a1 = 1;int _a2 = 1;
};int main()
{// 隐式类型转换,使用staticA aa1 = 1;A aa2 = static_cast<int>(1);return 0;
}

在这里插入图片描述

reinterpret_cast

  reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型(强制类型转换)

int main()
{int i = 1;// 强制类型转换 : reinterpret_castint* p = &i;int address = reinterpret_cast<int>(p);printf("%p %d\n", p, address);return 0;
}

在这里插入图片描述

const_cast

  const_cast最常用的用途就是删除变量的const属性,方便赋值

int main()
{const int i = 1;// 存放到寄存器中int* ptr = (int*)&i;(*ptr)++;cout << *ptr << endl;cout << i << endl;return 0;
}

在这里插入图片描述
  我们能够看到一个很奇怪的现象,我们将 i 地址处的数据++,该地址处的值修改了,但是 i 的值却没有修改,这是为什么呢?

实际是在C++程序中,使用 const 修饰的变量是存放在寄存器中的,最终打印该值是直接打印寄存器存储的值

dynamic_cast

  dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)

  1. dynamic_cast只能用于父类含有虚函数的类 。
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0。
class A
{
public:virtual void f(){}int _a1 = 1;
};class B : public A
{
public:int _b1 = 1;
};void func(A* pa)
{// 不差别转换,存在风险// 传A对象的地址,没有_b1成员,修改_b1成员则程序崩溃B* pb = (B*)pa;cout << pb << endl;pb->_b1++;
}int main()
{A a;B b;func(&a);func(&b);return 0;
}

在这里插入图片描述

class A
{
public:virtual void f(){}int _a1 = 1;
};class B : public A
{
public:int _b1 = 1;
};// 使用dynamic_cast,父类必须有虚函数
void func(A* pa)
{// pa指向a对象,转换成功// pa指向b对象,转换失败,返回nullptrB* pb = dynamic_cast<B*>(pa);if (pb){cout << pb << endl;pb->_b1++;}else{cout << "转换失败" << endl;}
}int main()
{A a;B b;func(&a);func(&b);return 0;
}

在这里插入图片描述

四、RTTI

RTTI:Run-time Type identification的简称,即:运行时类型识别

C++通过以下方式来支持RTTI:

  1. typeid运算符
  2. dynamic_cast运算符
  3. decltype


总结

  芜湖,马上就要迎来最后一节了!

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

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

相关文章

Android中Service在新进程中的启动流程

目录 1、Service与AMS交互框架介绍 1.1、认识AMS代表IActivityManager 1.2、认识客户端代表IApplicationThread 2、Service启动流程概览 我们知道Android有四大组件&#xff0c;Activity、Service、ContentProvider、Broadcast&#xff0c;每个组件在系统运行中或者我们编写…

docker 简要笔记

文章目录 一、前提内容1、docker 环境准备2、docker-compose 环境准备3、流程说明 二、打包 docker 镜像1、基础镜像2、国内镜像源3、基础的dockerfile4、打包镜像 四、构建运行1、docker 部分2、docker-compose 部分2.1、构建docker-compose.yml2.1.1、同目录构建2.1.2、利用镜…

利用Redis实现数据缓存

目录 1 为啥要缓存捏&#xff1f; 2 基本流程&#xff08;以查询商铺信息为例&#xff09; 3 实现数据库与缓存双写一致 3.1 内存淘汰 3.2 超时剔除&#xff08;半自动&#xff09; 3.3 主动更新&#xff08;手动&#xff09; 3.3.1 双写方案 3.3.2 读写穿透方案 3.3.…

活动回顾和预告|微软开发者社区 Code Without Barriers 上海站首场活动成功举办!

Code Without Barriers 上海活动回顾 Code Without Barriers&#xff1a;AI & DATA 深入探索人工智能与数据如何变革行业 2025年1月16日&#xff0c;微软开发者社区 Code Without Barriers &#xff08;CWB&#xff09;携手 She Rewires 她原力在大中华区的首场活动“AI &…

python爬虫入门(一) - requests库与re库,一个简单的爬虫程序

目录 web请求与requests库 1. web请求 1.1 客户端渲染与服务端渲染 1.2 抓包 1.3 HTTP状态代码 2. requests库 2.1 requests模块的下载 2.2 发送请求头与请求参数 2.3 GET请求与POST请求 GET请求的例子&#xff1a; POST请求的例子&#xff1a; 3. 案例&#xff1a;…

全连接神经网络(前馈神经网络)

目录 一、初步认识全连接神经网络 1、神经元 2、网络结构 3、正向传播算法 二、反向传播算法 1、理解 2、迭代流程 三、构建神经网络模型的基本步骤 四、线性回归神经网络结构 4.1 数据处理 1、数据导入 2、数据归一化处理 3、数据集划分 4、数据形状变换 4.2 模…

【C++初阶】第11课—vector

文章目录 1. 认识vector2. vector的遍历3. vector的构造4. vector常用的接口5. vector的容量6. vector的元素访问7. vector的修改8. vector<vector\<int\>>的使用9. vector的使用10. 模拟实现vector11. 迭代器失效11.1 insert插入数据内部迭代器失效11.2 insert插入…

Linux查看服务器的内外网地址

目录&#xff1a; 1、内网地址2、外网地址3、ping时显示地址与真实不一致 1、内网地址 ifconfig2、外网地址 curl ifconfig.me3、ping时显示地址与真实不一致 原因是dns缓存导致的&#xff0c;ping这种方法也是不准确的&#xff0c;有弊端不建议使用&#xff0c;只适用于测试…

PAT甲级-1024 Palindromic Number

题目 题目大意 一个非回文数&#xff0c;加上它的翻转数所得的和&#xff0c;进行k次&#xff0c;有可能会得到一个回文数。给出一个数n&#xff0c;限制相加次数为k次&#xff0c;如果小于k次就得到回文数&#xff0c;那么输出该回文数和相加的次数&#xff1b;如果进行k次还…

xss靶场

xss-labs下载地址&#xff1a;GitHub - do0dl3/xss-labs: xss 跨站漏洞平台 xss常见触发标签&#xff1a;XSS跨站脚本攻击实例与防御策略-CSDN博客 level-1 首先查看网页的源代码发现get传参的name的值test插入了html里头&#xff0c;还回显了payload的长度。 <!DOCTYPE …

数据结构——实验七·排序

欢迎各位大佬们来到Tubishu的博客&#x1f31f; Tubishu是一名计算机本科生&#xff0c;不定期发送一些在学校的成果供佬们消遣~希望能为佬的编程之路添砖加瓦⭐&#x1f525; 求各位大佬们垂怜&#x1f525;点赞评论一下呗&#x1f525;&#x1f525; 本文专栏 ➡️ 数据结构 …

使用vscode + Roo Code (prev. Roo Cline)+DeepSeek-R1使用一句话需求做了个实验

摘要 使用vscode、Roo Code和deepseek-reasoner进行了一个实验&#xff0c;尝试使用一句话需求来生成小红书封面图片。工具根据需求提供了详细的架构方案&#xff0c;包括技术栈选择、核心模块划分、目录结构建议等。然后&#xff0c;工具自动化地完成了开发和测试&#xff0c;…

vscode环境中用仓颉语言开发时调出覆盖率的方法

在vscode中仓颉语言想得到在idea中利用junit和jacoco的覆盖率&#xff0c;需要如下几个步骤&#xff1a; 1.在vscode中搭建仓颉语言开发环境&#xff1b; 2.在源代码中右键运行[cangjie]coverage. 思路1&#xff1a;编写了测试代码的情况&#xff08;包管理工具&#xff09; …

基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

前言&#xff1a; 本片博客只讲述了操作的大致流程&#xff0c;具体实现步骤并不标准&#xff0c;请以参考为准。 本文前提&#xff1a;熟悉使用webSocket 如果大家还不了解什么是WebSocket&#xff0c;可以参考我的这篇博客&#xff1a; rWebSocket 详解&#xff1a;全双工…

積分方程與簡單的泛函分析8.具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程

1)def求解具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程 设 是定义在上的连续对称核函数&#xff0c; 非齐次第二类弗雷德霍姆积分算子方程的形式为&#xff1a; &#xff0c; 其中是未知函数&#xff0c;是给定的连续函数&#xff0c;是参数。 2)def其特徵值是否一致…

RV1126画面质量四:GOP改善画质

一&#xff0e; 什么是 GOP GOP 实际上就是两个 I 帧的间隔&#xff0c;比方说分辨率是 1920 * 1080 50 帧&#xff0c;假设 GOP 为 5&#xff0c;那就是大概 2s 插入一个 I 帧。我们再 回顾下&#xff0c;H264/H265 的帧结构。H264/H265 分别分为三种帧类型&#xff1a;I 帧、…

一文了解二叉树的基本概念

文章目录 二叉树1二叉树的定义及其主要特征1.1二叉树的定义1.2二叉树的特点1.3二叉树的五种形态1.4二叉树与度为2的有序树的区别1.5几个特殊的二叉树1.6二叉树的性质 2二叉树的存储结构2.1二叉树的顺序存储2.2二叉树的链式存储 二叉树 1二叉树的定义及其主要特征 1.1二叉树的定…

MAX98357A一款数字脉冲编码调制(PCM)输入D类音频功率放大器

MAX98357A是一款数字脉冲编码调制&#xff08;PCM&#xff09;输入D类音频功率放大器&#xff0c;以下是对其的详细介绍&#xff1a; 一、主要特性 音频性能&#xff1a; 提供D类效率与AB类音频性能。支持高达3.2W&#xff08;4Ω负载&#xff0c;5V供电&#xff09;的输出功率…

nacos(基于docker最详细安装)

1、什么是Spring Cloud Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的开发风格做到一键启动和部署。…

78,【2】BUUCTF WEB .[安洵杯 2019]不是文件

进入靶场 解题过程 点击最下面的英文字即可上传图片 新建一个文本文档 里面内容为空 更改名字为 1,2,3,4,0x4f3a363a2268656c706572223a323a7b733a393a22002a00696676696577223b623a313b733a393a22002a00636f6e666967223b733a353a222f666c6167223b7d)#.png 知道id1&#x…