【C++】类型转换

【C++】类型转换

📝前言:

这篇文章我们来讲讲C++的类型转换

🎬个人简介:努力学习ing
📋个人专栏:C++学习笔记
🎀ZEEKLOG主页 愚润求学
🌄其他专栏:C语言入门基础python入门基础python刷题专栏Linux

文章目录

一,C语言类型转换

强制类型转换可以发生在转换有意义的地方。什么叫有意义?

  • 比如 intdouble,两个同为表示数据的大小。
  • 比如 指针(地址) 转 int,因为指针地址也是一个数字。但是不能指针转 double

类型转换发生的场景

  • 返回值接受类型和返回类型不相同
  • 形参与实参类型不相同
  • 表达式运算的项类型不相同
  • 赋值运算符,左右两边类型不相同
  • 等等…

1. 隐式类型转换

隐式类型转化:编译器在编译阶段自动动进行,能转就转,不能转就编译失败

int a =1;double b =2.1; cout << a + b << endl;// 输出 3.1

在运算时,a被隐式类型转换成了double再进行运算

2. 显式类型转换

显式强制类型转化:需要用户自己去显式在变量前用括号指定要转换的类型

int* ptr1 =&a;int c =(int)ptr1; cout << c << endl;// 输出:514849252

二,C++隐式类型转换(重点)

C++支持C语言的类型转换,同时还支持了:自定义类型 → 内置类型、内置类型 → 自定义类型、自定义类型 → 自定义类型

1. 内置转自定义

内置类型转成自定义类型需要构造函数的支持。实际上是:

  1. 把内置类型当参数,调用构造函数创建临时对象
  2. 用临时对象拷贝构造
  3. (不过上面两步可能会被编译器直接优化成一次构造)
classAdd{public:Add(int a):_a(a){}Add(int a,int b):_a(a),_b(b){}voidPrint(){ cout << _a + _b << endl;}private:int _a =1;int _b =1;};intmain(){ Add add1 =2;// 调用第一个拷贝构造 Add add2 ={2,2};// 调用第二个拷贝构造 add1.Print();// 输出 3 add2.Print();// 输出 4return0;}

如果在构造函数之前加explicit 则代表:该构造函数不能被隐式类型转换时调用。
explicit Add(int a)时,Add add1 = 2;会报错,因为创建临时对象时,无法调构造。

2. 自定义转内置

自定义转内置,要求:自定义类型内要支持:operator <转换类型>()的重载
为什么不是 <转换类型> operator(),因为这玩意已经被仿函数占用了

classA{public:A(double a):_a(a){}A(double a,int b):_a(a),_b(b){}operatordouble(){return _a;}private:double _a =1;int _b =1;};intmain(){ A a1 =2.1;double c = a1; cout << c << endl;// 输出: 2.1return0;}

3. 自定义转自定义

自定义A转自定义B:要求B有一个接受A为形参的构造函数(和内置转自定义类似)

classA{public:A(double a):_a(a){}A(double a,int b):_a(a),_b(b){}doubleGeta(){return _a;}private:double _a =1;int _b =1;};classB{public:B(A a1):_a(a1.Geta()){}voidPrint(){ cout << _a + _b << endl;}private:double _a =1.1;int _b =1;};intmain(){//A a1 = 2.1;//double c = a1;//cout << c << endl; // 输出: 2.1 A a1 =3.1; B b1 = a1; b1.Print();// 输出: 4.1return0;}

三,C++显式类型转换(重点)

1. 类型安全

类型安全指:编程语言在编译和运行时提供保护机制,避免非法的类型转换和操作。

C++并不是一门类型安全的语言,它允许我们类型转换,尽管我们可能有非法行为(这些非法行为即为不安全)
比如⼀个int*的指针强转成double*,然后用这个指针访问就会出现越界(指针的类型决定的是访问时一次"看"的空间

C++提出了4个显式的命名强制类型转换static_castreinterpret_castconst_castdynamic_cast,为了让类型转换相对而言更安全。(会检查转换是否合理)

2. 4个显式强制类型转换运算符

2.1 static_cast

static_cast

  • 检查时机:编译时
  • 使用场景:
    • 用于基本数据类型(如 int 转 double)、继承关系中的指针/引用转换(向上转换或向下转换,但是要确保安全性)
    • 不能用于无关类型(如 int* 转 double*)或移除 const 属性(把const变量转成非const不行)

示例:

double d =3.14;int i =static_cast<int>(d);// 基本类型转换 Base* base =newDerived(); Derived* derived =static_cast<Derived*>(base);// 向下转换(需确保安全)
  • 因为基类指针本身就指向派生类,再转换成派生类,不会有越界问题
  • 但是如果基类指针原本指向的就是基类,直接转换成派生类,就可能“多看”(有访问越界问题)

2.2 reinterpret_cast

reinterpret_cast

  • 检查时机:编译时
  • 用途:用于无关类型之间的转换(完全信任用户自己的行为,但是有极大的安全隐患)
    • int*char*,用户后续的访问行为可能会发生错误,引发未定义行为

示例:

int* ip =newint(42);char* cp =reinterpret_cast<char*>(ip);// 将 int* 转为 char*

2.3 const_cast

const_cast

  • 检查时机:编译时
  • 用途:添加或移除 constvolatile 属性(但是大多数是移除,因为添加可以隐式类型转换)

示例:

constint x =10;int* px =const_cast<int*>(&x);// 移除 const 属性*px =20;// 未定义行为(x 可能是常量存储区的值)volatile T* volatilePtr =...; T* nonVolatilePtr =const_cast<T*>(volatilePtr);// 移除 volatile

volatile就是用来确保每次获得变量值都去内存里面重新取,避免优化后直接从寄存器里面取,从而错过变量实际被修改了

2.4 dynamic_cast

dynamic_cast

  • 检查时机:运行时类型检查
  • 用途:用于继承体系中的安全向下转换(将基类指针或引用安全转换成派生类指针或引用)
    • 如果基类指针原本指向的就是派生类,则转换可以成功
    • 如果基类指针原本指向的指向基类,则转换失败(返回nullptr,抛出异常)
  • 要求:基类必须是多态类型(也就是基类中必须有虚函数)
    • (因为dynamic_cast是运行时通过虚表中(外)存储的type_info判断基类指针指向的是基类对象还是派生类对象)

示例:

classBase{public:virtual~Base(){}};classDerived:publicBase{}; Base* base =newDerived(); Derived* derived =dynamic_cast<Derived*>(base);// 安全向下转换if(derived){/* 成功 */}

四,RTTI

  • RTTI:运行时类型识别,程序在运行的时候才确定需要用到的对象是什么类型的。
  • RTTI 的代表运算符有两个,typeiddynamic_cast

typeid

  • typeid主要用于返回表达式的类型
  • typeid(e)e可以是任意表达式或类型的名字,typeid(e)的返回值是type_infotype_info派生类对象的引用,type_info可以只支持比较等于和不等于,name成员函数可以返回C风格字符串表示对象类型名字(不同编译器下可能不同)。可以参见:typeinfo头文件
  • e不属于类类型或者是⼀个不包含任何虚函数的类时,typeid返回的是运算
    对象的静态类型(此时是编译时确定)
  • e是定义了至少⼀个虚函数的类的左值时,typeid的返回结果直到运行时才会求得

示例(编译器为vs2022):

#include<typeinfo>intmain(){int x =42;// const std::type_info& ti = typeid(x); // typeid 返回的是 const std::type_info& std::cout <<typeid(x).name()<< std::endl;// 输出: int (不同编译器的输出效果可能不同,比如可能拿 i 表示 int)return0;}

🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

Read more

全员DeepSeek时代,前端能做些什么?

全员DeepSeek时代,前端能做些什么?

全员DeepSeek时代,前端能做些什么? 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc DeepSeek开发阶段测试阶段部署阶段智能代码生成设计稿转代码实时代码审查测试用例生成自动化问题定位构建优化建议性能预测模型 一、DeepSeek带来的前端范式变革 1.1 传统前端开发痛点分析 DeepSeek通过以下方式改变工作流程: 1. 代码生成效率提升:组件级代码生成速度提升300% 2. 缺陷预防率提高:静态分析拦截87%的潜在问题 3. 性能优化自动化:构建产物体积平均缩减42% 二、开发阶段的DeepSeek实践 2.1 智能组件生成 // 用户输入自然语言描述const prompt ="生成一个带懒加载的图片轮播组件,支持手势滑动,要求React实现";// DeepSeek生成结果exportconstLazySwiper=({ images })=>{const[swiperRef, setSwiperRef]=useState(nu

By Ne0inhk
前端岗面试30万字原题含答案

前端岗面试30万字原题含答案

我们正处在前端发展的一个微妙节点。 曾几何时,几句 HTML、CSS 加个 jQuery 特效就能轻松拿 Offer;后来,掌握 Vue 或 React 便能成为市场宠儿。但现在,当你翻开这本“前端岗面试30万字原题含答案”时,我们所面对的前端世界,已经悄然变成了一场 “冰与火之歌”。 大环境的“冰”:在存量博弈中寻找缺口 当下的技术招聘市场,用一个字形容就是 “卷”。互联网行业从野蛮生长步入精耕细作,HC(招聘名额)紧缩,而涌入的求职者却依旧庞大。大厂不再仅仅为了业务扩张而招人,更看重候选人的不可替代性。 你不仅要与同级的毕业生竞争,还要与众多因公司业务调整而释放出来的、经验丰富的中高级开发者同台竞技。这就导致了一个现象:面试难度呈指数级上升。以前“背八股”就能通关,现在面试官更擅长从一个简单的知识点出发,逐步深挖到你知识体系的盲区。 面试的“火”:从“会用”到“

By Ne0inhk
【最新版】防伪溯源一体化管理系统+uniapp前端+搭建教程

【最新版】防伪溯源一体化管理系统+uniapp前端+搭建教程

一.介绍 防伪溯源一体化管理系统基于ThinkPHP和Uniapp进行开发的多平台(微信小程序、H5网页)溯源、防伪、管理一体化独立系统,拥有强大的防伪码和溯源码双码生成功能(内置多种生成规则)、批量大量导出防伪和溯源码码数据、支持代理商管理端(团队管理、采购,邀请代理商、出库等功能)、支持招商经理管理端(可管理代理商团队,邀请代理商,数据统计,采购订单统计),支持出厂员端(出库、入库)、文章资讯、自定义展示查询页显示数据、查询记录、溯源记录追踪等功能。前后端无加密源代码和数据库,独立部署。 二.搭建环境 系统环境:CentOS、 运行环境:宝 塔 Linux 网站环境:Nginx 1.2.22 + MySQL 5.6 + PHP-7.4 常见插件:fileinfo

By Ne0inhk
Java Web 开发:JSON 基础 + @Test 测试 + Cookie/Session/ 请求处理

Java Web 开发:JSON 基础 + @Test 测试 + Cookie/Session/ 请求处理

个人主页:♡喜欢做梦 欢迎  👍点赞  ➕关注  ❤️收藏  💬评论 目录 编辑 🍍JSON的概念  🍐概念  🍐@Test注解 🍑什么是@Test? 🍑与JSON关联 🍑@Test标记的方法与main方法的区别  🍍JSON语法  🍐核心数据类型  🍐常见使用 🍑对象 🍑数组  🍑JSON字符串和Java对象的互转 🍑传递JSON 🍑获取URL中的参数 🍑上传文件:@RequestPart  🍍Cookie和Seeion  🍐Cookie 🍑什么是Cookie? 🍑Cookie的获取  🍐Session 🍑什么是Session?  🍐Cookie和Session之间的关系 🍑Session的存储 🍑Session的获取 🍍获取header 🍍JSON的概念  🍐概念 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。他基于JavaScript的一个子集,但采用了独立语言的文

By Ne0inhk