【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

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术 一、引言 在科学计算和数据分析中,函数与方程的可视化是理解数学关系和物理现象的重要工具。本文基于Python的Tkinter和Matplotlib库,实现一个功能完善的函数与方程可视化工具,支持显函数、隐函数、特殊曲线(如心形线)及物理场分布(如电势)的交互式绘图,并提供安全的表达式解析、图像保存等功能。 二、核心技术架构 2.1 系统架构与技术选型 * 界面层:使用Tkinter构建GUI,包含类型选择、表达式输入、预设函数下拉菜单等控件 * 计算层: * 显函数:通过np.linspace生成采样点,安全计算函数值 * 隐函数:基于等高线算法contour绘制等值线 * 安全机制:通过正则表达式过滤非法字符,限制白名单函数防止代码注入 * 可视化层:Matplotlib实现图表渲染,支持动态更新和交互式工具条 2.2 安全表达式解析 defis_valid_expression(expr):""

By Ne0inhk
《C++进阶之STL》【unordered_set/unordered_map 使用介绍】

《C++进阶之STL》【unordered_set/unordered_map 使用介绍】

【unordered_set/unordered_map 使用介绍】目录 * 前言 * ------------unordered_set------------ * 一、介绍 * 二、接口 * 1. 常见的构造 * 2. 容量的操作 * std::unordered_set::size * std::unordered_set::empty * 3. 访问的操作 * std::unordered_set::find * std::unordered_set::count * 4. 修改的操作 * std::unordered_set::clear * std::unordered_set::swap * std::unordered_set::insert * std:

By Ne0inhk
Python 驱动浏览器自动化:Playwright + AI 的 2026 最佳实践

Python 驱动浏览器自动化:Playwright + AI 的 2026 最佳实践

摘要:在 Web 自动化领域,Selenium 曾经的霸主地位已成历史,Playwright 凭其“快、稳、强”的现代特性成为了新标准。而在 2026 年,随着 LLM(大语言模型)和视觉多模态模型的爆发,自动化测试与 RPA(机器人流程自动化)迎来了范式革命。本文将深度解析 Playwright 的核心架构,并手把手教你构建一个具备“自愈能力”的 AI 驱动自动化 Agent。本文超 7000 字,包含大量实战代码与反爬对抗技巧。 第一章:Selenium 已死,Playwright 当立? 1.1 自动化的“不可能三角” 长期以来,Web 自动化工程师都在速度、稳定性和抗检测性之间做取舍: * Selenium:

By Ne0inhk
蓝香蕉代码 |【鸿蒙电脑开发编译C/C++】

蓝香蕉代码 |【鸿蒙电脑开发编译C/C++】

lycium_plusplus介绍 项目地址 lycium++支持鸿蒙电脑使用 上次我们介绍了lycium++框架的扩展,最近针对在鸿蒙电脑上使用框架也进行下介绍 如何使用 解决了什么问题 lycium++框架支持在win/mac/linux上进行交叉编译,支持一件打包hnp文件,通过这些hnp作为组件与应用一起安装到鸿蒙电脑上,在HarmonyOS上使用该框架也成为了可能。本次我们将框架在鸿蒙电脑上进行了适配,通过交叉编译解决了在鸿蒙电脑上执行编译的工具最小集,并伴随DevBox、Python安装器、DevNode-OH、GitNext几个核心应用的上架,解决了在鸿蒙电脑中,通过命令行编译C/C++代码的核心问题。 环境介绍 * 设备:我使用的MateBook Pro已经升级到6.0.0.115版本,建议升级到该版本以上 * 代码管理工具:GitNext,作为代码管理工具下载管理三方库等,下载后可在系统终端中使用(个人推荐),也可以使用界面管理 * 编译工具链:DevBox,包含了llvm、clang、autoconf、bash、cmake、make、nin

By Ne0inhk