当前位置: 首页 > article >正文

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


总结

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

相关文章:

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

文章目录 前言一、C语言中的类型转换二、为什么C会有四种类型转换&#xff1f;内置类型 -> 自定义类型自定义类型 -> 内置类型自定义类型 -> 自定义类型隐式类型转换的坑 三、C强制类型转换static_castreinterpret_castconst_castdynamic_cast 四、RTTI总结 前言 Hell…...

4.flask-SQLAlchemy,表Model定义、增删查改操作

介绍 SQLAlchemy是对数据库的一个抽象 开发者不用直接与SQL语句打交道 Python对象来操作数据库 SQLAlchemy是一个关系型数据库 安装 flask中SQLAlchemy的配置 from flask import Flask from demo.user_oper import userdef create_app():app Flask(__name__)# 使用sessi…...

基于 WEB 开发的手机销售管理系统设计与实现内容

标题:基于 WEB 开发的手机销售管理系统设计与实现 内容:1.摘要 摘要&#xff1a;随着智能手机的普及和电子商务的快速发展&#xff0c;手机销售行业面临着越来越多的挑战和机遇。为了提高销售效率和管理水平&#xff0c;本文设计并实现了一个基于 WEB 的手机销售管理系统。该系…...

JavaScript 验证 API:全面解析与实战指南

JavaScript 验证 API:全面解析与实战指南 引言 随着互联网技术的不断发展,前端开发领域的重要性日益凸显。JavaScript 作为前端开发的核心技术之一,其功能性和可扩展性得到了广泛关注。验证功能是JavaScript中不可或缺的一部分,它保证了用户输入数据的正确性和有效性。本…...

20250122-正则表达式

1. 正则标记 表示一位字符&#xff1a;\\ 表示指定的一位字符&#xff1a;x 表示任意的一位字符&#xff1a;. 表示任意一位数字&#xff1a;\d 表示任意一位非数字&#xff1a;\D 表示任意一个字母&#xff1a;[a-zA-Z]&#xff08;大写或小写&#xff09; 表示任意一个…...

SpringBoot3+Vue3开发学生选课管理系统

功能介绍 分三个角色登录&#xff1a;学生登录&#xff0c;老师登录&#xff0c;教务管理员登录&#xff0c;不同用户功能不同&#xff01; 1.学生用户功能 选课记录&#xff0c;查看选课记录&#xff0c;退选。选课管理&#xff0c;进行选课。通知管理&#xff0c;查看通知消…...

Effective C++ 规则47: 请使用 Traits Class 表现类型信息

1、背景 C 是一种静态类型语言&#xff0c;类型的特性在编译期就可以被识别和操作。为了更好地利用编译期信息来编写高效、灵活、可维护的代码&#xff0c;C 提供了一些技术来“萃取”或“提取”类型的相关信息。即利用 traits 类来封装和提取类型信息&#xff0c;以便在编译期…...

媒体新闻发稿要求有哪些?什么类型的稿件更好通过?

为了保证推送信息的内容质量&#xff0c;大型新闻媒体的审稿要求一向较为严格。尤其在商业推广的过程中&#xff0c;不少企业的宣传稿很难发布在这些大型新闻媒体平台上。 媒体新闻发稿要求有哪些&#xff1f;就让我们来了解下哪几类稿件更容易过审。 一、媒体新闻发稿要求有哪…...

“AI教学实训系统:打造未来教育的超级引擎

嘿&#xff0c;各位教育界的伙伴们&#xff0c;今天我要跟你们聊聊一个绝对能让你们眼前一亮的教学神器——AI教学实训系统。作为资深产品经理&#xff0c;我可是亲眼见证了这款系统如何颠覆传统教学&#xff0c;成为未来教育的超级引擎。 一、什么是AI教学实训系统&#xff1f…...

基于JAVA的微信点餐小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

【2024年华为OD机试】(A卷,200分)- 查找树中元素 (JavaScriptJava PythonC/C++)

一、问题描述 题目解析 题目描述 题目要求根据输入的坐标 (x, y) 在树形结构中找到对应节点的内容值。其中: x 表示节点所在的层数,根节点位于第0层,根节点的子节点位于第1层,依此类推。y 表示节点在该层内的相对偏移,从左至右,第一个节点偏移为0,第二个节点偏移为1,…...

Pyecharts图表交互功能提升

在数据可视化中&#xff0c;交互功能可以极大地提升用户体验&#xff0c;让用户能够更加深入地探索数据。Pyecharts 提供了多种强大的交互功能&#xff0c;本篇将重点介绍如何使用缩略轴组件、配置图例交互&#xff0c;让我们的数据可视化作品更加生动有趣。 一、缩略轴组件使…...

用layui表单,前端页面的样式正常显示,但是表格内无数据显示(数据库连接和获取数据无问题)——已经解决

这是我遇到的错误 原因&#xff1a;后端控制台的数据格式没有设置清楚 解决&#xff1a;1、加注释 ResponseBody &#xff0c;确保返回的是json数据。 2、要传三个参数到前端&#xff0c;如下图第二个红色框框所示。因为layui框架代码如果未修改&#xff0c;默认要传入这三个…...

单片机基础模块学习——按键

一、按键原理图 当把跳线帽J5放在右侧&#xff0c;属于独立按键模式&#xff08;BTN模式&#xff09;&#xff0c;放在左侧为矩阵键盘模式&#xff08;KBD模式&#xff09; 整体结构是一端接地&#xff0c;一端接控制引脚 之前提到的都是使用了GPIO-准双向口的输出功能&#x…...

elk 安装

创建elk网络 docker network create -d bridge elkelasticsearch 创建目录 mkdir -p /data/elasticsearch/{conf,logs,data,plugins}vim /data/elasticsearch/conf/elasticsearch.ymlcluster.name: "es-cluster" network.host: 0.0.0.0 xpack.security.enabled: tr…...

2025年1月22日(什么是扫频)

扫频&#xff08;Sweep Frequency&#xff09;是一种信号处理技术&#xff0c;通常用于系统识别、频率响应分析和特性测试。它通过发送一个频率逐渐变化的信号&#xff08;通常是正弦波或线性调频信号&#xff09;来激励系统&#xff0c;然后测量系统的响应。这种方法可以帮助我…...

mybatis是什么?有什么作用?mybatis的简单使用

mybatis是什么&#xff1f; MyBatis 是一个持久层框架。 有什么作用&#xff1f; 简化了对数据库数据的操作。 如何简化数据操作的&#xff1f; MyBatis 通过提供 SQL 映射、动态 SQL、结果映射、事务管理等功能&#xff0c;我们直接去用就可以了。 怎么使用&#xff1f;&…...

webpack 打包自己的--windows

第一步安装node 1、安装nodejs:https://nodejs.org/zh-cn/download/releases/ 一、Window系统配置&#xff1a; 打开命令窗口,进入当前工程目录 npm配置淘宝镜像:npm config set registry http://registry.npm.taobao.org/ npm安装parcel-bundler:npm install -g parcel-bund…...

微服务学习-Nacos 注册中心实战

1. 注册中心的设计思路 1.1. 微服务为什么会用到注册中心&#xff1f; 服务与服务之间调用需要有服务发现功能&#xff1b;例如订单服务调用库存服务&#xff0c;库存服务如果有多个&#xff0c;订单服务到底调用那个库存服务呢&#xff08;负载均衡器&#xff09;&#xff0…...

MySQL数据库 - 语法知识

一 数据模型 1 关系型数据库管理系统&#xff08;RDBMS&#xff09; 概念&#xff1a;建立在关系模型基础上&#xff0c;有多张相互连接的二维表组成的数据库。 特点&#xff1a; 使用表存储数据&#xff0c;格式统一&#xff0c;便于维护。使用SQL语言操作&#xff0c;标准…...

Zookeeper(28)Zookeeper的线性化写入和顺序一致性读是什么?

Zookeeper 是一个分布式协调服务&#xff0c;它在设计上提供了强一致性的保证&#xff0c;其中包括线性化写入和顺序一致性读。这两种一致性模型确保了在分布式系统中数据的一致性和操作的确定性。 线性化写入&#xff08;Linearizable Writes&#xff09; 线性化写入保证在任…...

kamailio-5.8.4-centos9编译

安装必要的依赖包 在开始编译之前&#xff0c;你需要安装编译 Kamailio 所需的一些基础依赖包&#xff1a; dnf install -y make gcc gcc-c flex bison libxml2-devel openssl-devel sqlite-devel mysql-devel pcre-devel libcurl-devel下载并解压 Kamailio 源码包 假设你已经…...

有限元分析学习——Anasys Workbanch第一阶段笔记(15)接触间隙处理与赫兹接触

目录 0 序言 1 接触的间隙处理 1.1 结果对比 1.2 处理方法 2 赫兹接触 0 序言 本章主要介绍间隙出现时的三种解决方法&#xff0c;齿轮点蚀/表面剥落涉及的赫兹接触的一些理论知识。 1 接触的间隙处理 在实际产品过程中&#xff0c;很多时候由于设计问题&#xff0c;原本…...

Angular 2 表单深度解析

Angular 2 表单深度解析 引言 Angular 2作为现代前端开发的框架之一,以其灵活性和强大的功能赢得了众多开发者的青睐。在Angular 2中,表单处理是其中一个重要且复杂的部分。本文将深入解析Angular 2的表单,从基础知识到高级应用,旨在帮助开发者更好地理解和运用Angular 2…...

查询本周一到周五的数据

查询sql SELECT CASEWHEN TO_CHAR(T.BEGINDATE, D) 2 THEN 周一WHEN TO_CHAR(T.BEGINDATE, D) 3 THEN 周二WHEN TO_CHAR(T.BEGINDATE, D) 4 THEN 周三WHEN TO_CHAR(T.BEGINDATE, D) 5 THEN 周四WHEN TO_CHAR(T.BEGINDATE, D) 6 THEN 周五END AS DAY_NAME,T.COLUMN1,T.COL…...

【Linux】命令为桥,存在为岸,穿越虚拟世界的哲学之道

文章目录 Linux基础入门&#xff1a;探索操作系统的内核与命令一、Linux背景与发展历史1.1 Linux的起源与发展1.2 Linux与Windows的对比 二、Linux的常用命令2.1 ls命令 - "List"&#xff08;列出文件)2.2 pwd命令 - "Print Working Directory"&#xff08…...

【技术】TensorRT 10.7 安装指南(Ubuntu22.04)

原文链接&#xff1a;https://mengwoods.github.io/post/tech/008-tensorrt-installation/ 本文安装的版本如下&#xff1a; Ubuntu 22.04 Nvidia Driver 538.78 CUDA 12.2 cuDNN 8.9.7 TensorRT 10.7 安装前的准备&#xff08;可选&#xff09; 在安装新版本之前&#xf…...

2025美赛美国大学生数学建模竞赛A题完整思路分析论文(43页)(含模型、可运行代码和运行结果)

2025美国大学生数学建模竞赛A题完整思路分析论文 目录 摘要 一、问题重述 二、 问题分析 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1样例代码&#xff08;仅供参考&#xff09; 4.1.4问题1样例代码运行结果&…...

DDD架构实战第七讲总结:分层模型和代码组织

云架构师系列课程之DDD架构实战第七讲总结:分层模型和代码组织 一、引言 在前几讲中,我们介绍了领域驱动设计(DDD)的基本构造块和生命周期模型中的聚合。本讲将重点讨论如何将这些构造块和代码组织起来,探讨分层架构和六边形模型,以及如何组织代码结构。 二、工厂和资…...

http的请求体各项解析

一、前言 做Java开发的人员都知道&#xff0c;其实我们很多时候不单单在写Java程序。做的各种各样的系统&#xff0c;不管是PC的 还是移动端的&#xff0c;还是为别的系统提供接口。其实都离不开http协议或者https 这些东西。Java作为编程语言&#xff0c;再做业务开发时&#…...