C++Cherno 学习笔记day17 [66]-[70] 类型双关、联合体、虚析构函数、类型转换、条件与操作断点

b站Cherno的课[66]-[70]

  • 一、C++的类型双关
  • 二、C++的union(联合体、共用体)
  • 三、C++的虚析构函数
  • 四、C++的类型转换
  • 五、条件与操作断点——VisualStudio小技巧

一、C++的类型双关

作用:在C++中绕过类型系统
在这里插入图片描述

C++是强类型语言
有一个类型系统,不是所有东西都用auto去声明
可以用auto,毕竟它也是一个关键字

但在JavaScript中,没有变量类型的概念
在创建变量时,不需要声明变量类型
当我们接受它作为函数的参数时,没有真正的类型系统

但C++有一个类型系统
当我们创建变量的时候,必须声明整数或双精度数或布尔数或结构体或者类等等
然而,这种类型系统并不像在其他语言中那样强制,比如java
它们的类型很难绕开,包括C#也是
你虽然也可以绕开类型系统,但要做更多的工作

在C++中,虽然类型是由编译器强制执行的,但您可以直接访问内存
这意味着在代码中一直使用这种类型,比如整数,但实际上,我现在要把这段内存,同样的内存,当作double类型,或者是class类型等
可以很容易地绕过类型系统
你是否要用,取决于你的实际情况
在某些情况下,您绝对不应该规避类型系统,因为类型系统存在是有原因的

#include <iostream>int main()
{int a = 50;//double value = a; 隐式转换double value = (double)a; // 显式转换std::cout << value << std::endl;std::cin.get();
}

在这里插入图片描述

#include <iostream>int main()
{int a = 50;//double value = a; 隐式转换//double value = (double)a; 显式转换double& value = *(double*)&a;value = 0.0;std::cout << value << std::endl;std::cin.get();
}

在这里插入图片描述

#include <iostream>struct Entity {int x, y;
};int main()
{Entity e = { 5, 8 };// 回到了原始的内存操作int* position = (int*)&e;int y = *(int*)((char*)&e + 4);std::cout << y << std::endl;std::cin.get();
}

在这里插入图片描述
我们可以用不同的方式解析同一段内存,从而得到不同的结果,类型只是我们约定的解析内存的方式

类型双关:我要把我拥有的这段内存,当作不同类型的内存来对待
我们需要做的只是将该类型作为指针,然后将其转换为另一个指针
然后如果有必要,还可以对它进行解引用

二、C++的union(联合体、共用体)

在这里插入图片描述

联合体有点像类类型,或者结构体类型
只不过它一次只能占用一个成员的内存
这意思是说,通常如果我们有一个结构体,我们声明比如4个浮点数,
我们可以有4乘以4个字节在这个结构体中,总共是16个字节
因为我们有四个成员,而且很明显
当你不断向类或结构体中添加更多成员时,其大小会不断增长

一个联合体只能有一个成员
如果要声明四个浮点数 ABCD 联合体的大小仍然是4个字节,当改变ABCD的值的时候,内存是一样的
改变a设成5 b的值也是5

你可以像使用结构体或类一样使用它们
你也可以给它添加静态函数或者普通函数、方法等等

通常union是匿名使用的,但是匿名union不能含有成员函数

通常被用来做类型双关,union可读性更强

#include <iostream>struct Vector2 {float x, y;
};struct Vector4 {float x, y, z, w;
};void PrintVector2(const Vector2& vector)
{std::cout << vector.x << "," << vector.y << std::endl;
}int main()
{struct Union{union{float a;int b;};};Union u;u.a = 2.0f;std::cout << u.a << "," << u.b << std::endl;
}

在这里插入图片描述

#include <iostream>struct Vector2 {float x, y;
};struct Vector4 {union{// 匿名的,只是一种数据结构,并没有添加任何东西struct{float x, y, z, w;};struct{Vector2 a, b;};};
};void PrintVector2(const Vector2& vector)
{std::cout << vector.x << "," << vector.y << std::endl;
}int main()
{Vector4 vector = { 1.0f,2.0f,3.0f,4.0f };//vector.x = 2.0f;PrintVector2(vector.a);PrintVector2(vector.b);vector.z = 500.0f;std::cout << "--------------------------" << std::endl;PrintVector2(vector.a);PrintVector2(vector.b);std::cin.get();
}

在这里插入图片描述
union里的成员会共享内存,分配的大小是按最大成员的sizeof, 视频里有两个成员,也就是那两个结构体,改变其中一个另外一个里面对应的也会改变. 如果是这两个成员是结构体struct{ int a,b} 和 int k , 如果k=2 ; 对应 a也=2 ,b不变; union我觉得在这种情况下很好用,就是用不同的结构表示同样的数据 ,那么你可以按照获取和修改他们的方式来定义你的 union结构 很方便

一个联合体的应用场景:开发弱类型语言。例如js,let a=2; 紧接着写a=“abc”;变量a在一个时间点只会是一种类型,那就可以定义一个联合体来表示变量的值。

三、C++的虚析构函数

复习:析构函数~(销毁对象) 虚函数virtual

析构函数:在销毁对象时运行,卸载变量,清理使用过的内存,同时适用于栈和堆分配的对象
虚函数:允许我们在子类中重写方法

虚析构函数:二者结合,对于处理多态问题非常重要

#include <iostream>class Base
{
public:Base() { std::cout << "Base Constructor\n"; }~Base() { std::cout << "Base Destrcctor\n"; }
};class Derived : public Base
{
public:Derived() { std::cout << "Derived Constructor\n"; }~Derived() { std::cout << "Derived Destrcctor\n"; }
};int main()
{Base* base = new Base();delete base;std::cout << "----------------\n" << std::endl;Derived* derived = new Derived();delete derived;std::cin.get();
}

在这里插入图片描述

int main()
{Base* base = new Base();delete base;std::cout << "----------------\n" << std::endl;Derived* derived = new Derived();delete derived;std::cout << "----------------\n" << std::endl;Base* poly = new Derived();delete poly;std::cin.get();
}
// 只有基类的析构函数被调用,派生类的的析构函数没有被调用
// 这样会导致内存泄露

在这里插入图片描述
虚析构函数不是覆写析构函数,而是加上一个析构函数
如果我把基类析构函数改为虚函数
它实际上会调用两个(析构函数)
它会先调用派生类析构函数,然后在层次结构中向上,调用基类析构函数
标记为virtual,意味着c++就会知道在层次结构下的这个方法可能被重写了

一定要确保声明析构函数是虚函数,如果你允许它有子类的话

!!!如果用基类指针来引用派生类对象,那么基类的析构函数必须是 virtual 的,否则 C++ 只会调用基类的析构函数,不会调用派生类的析构函数。

四、C++的类型转换

C++是强类型语言,意味着存在一个类型系统,并且类型是强制的

#include <iostream>class Base
{
public:Base() {}~Base() {}
};class Derived : public Base
{
public:Derived() {}~Derived() {}
};class AnotherClass : public Base
{
public:AnotherClass() {}~AnotherClass() {}
};int main()
{	// 隐式转换//int a = 5;//double value = a;double value = 5.25;//int a = value;//int a = (int)value;double a = value + 5.3;std::cout << a << std::endl;std::cin.get();
}

在这里插入图片描述

#include <iostream>class Base
{
public:Base() {  }~Base() {  }
};class Derived : public Base
{
public:Derived() {  }~Derived() {  }
};class AnotherClass : public Base
{
public:AnotherClass() {}~AnotherClass() {}
};int main()
{	// 隐式转换//int a = 5;//double value = a;double value = 5.25;//int a = value;//int a = (int)value;// C语言风格类型转换double a = (int)value + 5.3;std::cout << a << std::endl;std::cin.get();
}

在这里插入图片描述

#include <iostream>class Base
{
public:Base() {  }virtual ~Base() {  }
};class Derived : public Base
{
public:Derived() {  }~Derived() {  }
};class AnotherClass : public Base
{
public:AnotherClass() {}~AnotherClass() {}
};int main()
{	Derived* derived = new Derived();Base* base = derived;Derived* ac = dynamic_cast<Derived*>(base);std::cin.get();
}

C++风格 共四种主要的cast 类型转换操作符
一个是 static_cast,还有reinterpret_cast、dynamic_cast、const_cat

static_cast:静态类型转换
reinterpret_cast:把这段内存重新解释成别的东西
const_cat:移除或添加变量的const限定
dynamic_cast:很好的方法来查看是否转换成功,与运行时类型信息RTTI(runtime type information)紧密相关
regex正则表达式

五、条件与操作断点——VisualStudio小技巧

关于条件与操作(conditions and actions)应用在断点上
操作断点是允许我们采取某种动作
一般是在碰到断点时打印一些东西到控制台

两种类型的操作断点:
操作断点和条件断点
在这里插入图片描述

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

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

相关文章

011_异常、泛型和集合框架

异常、泛型和集合框架 异常Java的异常体系异常的作用 自定义异常异常的处理方案异常的两种处理方式 泛型泛型类泛型接口泛型方法、通配符和上下限泛型支持的类型 集合框架集合体系结构Collection Collection集合Collection的遍历方式认识并发修改异常问题解决并发修改异常问题的…

Kubernetes 集群搭建(三):使用dashboard用户界面(需要访问外网获取yaml)

&#xff08;一&#xff09;简介 K8s Dashboard是Kubernetes提供的一种基于Web的用户界面工具&#xff0c;用于可视化地管理和监控Kubernetes集群 主要功能&#xff1a; 资源查看与管理&#xff1a; 查看Kubernetes集群中的各种资源&#xff0c;如节点、Pod、服务、部署等。 对…

【数据挖掘】岭回归(Ridge Regression)和线性回归(Linear Regression)对比实验

这是一个非常实用的 岭回归&#xff08;Ridge Regression&#xff09;和线性回归&#xff08;Linear Regression&#xff09;对比实验&#xff0c;使用了 scikit-learn 中的 California Housing 数据集 来预测房价。 &#x1f4e6; 第一步&#xff1a;导入必要的库 import num…

大疆无人机系列知识

目录 知识 开发者文档 &#xff08;上云&#xff09; 无人机的应用 知识 大疆行业无人机接入音视频平台协议详解_大疆无人机 视频流-CSDN博客 开发者文档 &#xff08;上云&#xff09; 上云API 无人机的应用 【大疆无人机地图测绘技术学习&#xff1a;高精度、高效率的…

CNN注意力机制的进化史:深度解析10种注意力模块如何重塑卷积神经网络

&#x1f31f; 引言&#xff1a;注意力为何改变CNN的命运&#xff1f; 就像人类视觉会优先聚焦于重要信息&#xff0c;深度学习模型也需要"学会看重点"。从2018年SENet首提通道注意力&#xff0c;到2024年SSCA探索空间-通道协同效应&#xff0c;注意力机制正成为CNN…

Linux/树莓派网络配置、远程登录与图形界面访问实验

一.准备工作 1.修改网络适配器&#xff08;选择本机网卡&#xff09; 2.创建一个新的用户。 3.使用新用户登录&#xff0c;使用ip a指令查看IP&#xff08;现代 Linux 发行版&#xff08;如 Ubuntu、Debian、CentOS、Fedora 等&#xff09;&#xff09;。 通过sudo arp-sca…

Python----TensorFlow(TensorFlow介绍,安装,主要模块,高级功能)

一、TensorFlow TensorFlow 是由谷歌大脑团队于 2015 年推出的开源机器学习框架。作为深度学习的第二代系统&#xff0c;TensorFlow 支持多种编程语言&#xff0c;包括 Python、C、Java 和 Go&#xff0c;广泛应用于 CNN、RNN 和 GAN 等深度学习算法。 TensorFlow 可以…

【动态规划】 深入动态规划 回文子串问题

文章目录 前言例题一、回文子串二、 最长回文子串三、回文串分割IV四、分割回文串II五、最长回文子序列六、让字符串成为回文串的最小插入次数 结语 前言 那么&#xff0c;什么是动态规划中的回文子串问题呢&#xff1f; 动态规划中的回文子串问题是一个经典的字符串处理问题。…

lodash库介绍(一个现代JavaScript实用工具库,提供模块化、性能优化和额外功能)JavaScript库(防抖、节流、函数柯里化)JS库

https://www.lodashjs.com/ 文章目录 Lodash库全解析简介核心优势一致性API模块化设计性能优化 常用功能分类数组操作对象操作函数增强 高级应用场景数据转换链函数组合 性能考量大数据集处理 最佳实践按需引入利用FP模块 结语 Lodash库全解析 简介 Lodash是一个现代JavaScri…

Spring MVC 国际化机制详解(MessageSource 接口体系)

Spring MVC 国际化机制详解&#xff08;MessageSource 接口体系&#xff09; 1. 核心接口与实现类详解 接口/类名描述功能特性适用场景MessageSource核心接口&#xff0c;定义消息解析能力支持参数化消息&#xff08;如{0}占位符&#xff09;所有国际化场景的基础接口Resource…

PyTorch张量范数计算终极指南:从基础到高阶实战

在深度学习领域&#xff0c;张量范数计算是模型正则化、梯度裁剪、特征归一化的核心技术。本文将以20代码实例&#xff0c;深度剖析torch.norm的9大核心用法&#xff0c;并揭示其在Transformer模型中的关键应用场景。 &#x1f680; 快速入门&#xff08;5分钟掌握核心操作&…

荣耀90 GT信息

外观设计 屏幕&#xff1a;采用 6.7 英寸 AMOLED 荣耀绿洲护眼屏&#xff0c;超窄边框设计&#xff0c;其上边框 1.6mm&#xff0c;左右黑边 1.25mm&#xff0c;屏占较高&#xff0c;带来更广阔的视觉体验。屏幕还支持 120Hz 自由刷新率&#xff0c;可根据使用场景自动切换刷新…

【Java中级】11章、枚举 - java引用数据类型,枚举介绍、快速入门,了解枚举类的基本使用方式【1】

文章内容&#xff1a; 自定义实现枚举enum关键字实现枚举 ❤️内容涉及枚举的定义&#xff0c;快速入门&#xff0c;注意事项和小题巩固知识点 &#x1f308; 跟着B站一位老师学习的内部类内容&#xff0c;现写这篇文章为学习内部类的小伙伴提供思路支持&#xff0c;希望可以一…

局域网访问 Redis 方法

局域网访问 Redis 方法 默认情况下&#xff0c;Redis 只允许本机 (127.0.0.1) 访问。如果你想让局域网中的其他设备访问 Redis&#xff0c;需要 修改 Redis 配置&#xff0c;并确保 防火墙放行端口。 方法 1&#xff1a;修改 Redis 配置 1. 修改 redis.conf&#xff08;或 me…

如何应对客户频繁变更需求

如何应对客户频繁变更需求&#xff1f;要点包括&#xff1a; 快速响应、深入沟通、灵活规划、过程记录、风险管控。这些策略既能降低项目失控风险&#xff0c;也能帮助团队在变动环境中保持高效率。其中深入沟通尤为关键&#xff0c;它不仅能够让团队第一时间了解客户意图&…

Set 集合

默认情况下&#xff0c; Scala 使用的是不可变集合&#xff0c; 如果你想使用可变集合&#xff0c; 需要引用 scala.collection.mutable.Set Set 默认是不可变集合&#xff0c;数据无序 数据不可重复 遍历集合 创建可变集合 mutable.Set 打印集合 集合添加元素 向集合中…

最新 OpenHarmony 系统一二级目录整理

我们在学习 OpenHarmony 的时候&#xff0c;如果对系统的目录结构了解&#xff0c;那么无疑会提升自己对 OpenHarmony 更深层次的认识。 于是就有了今天的整理。 首先在此之前&#xff0c;我们要获取源码 获取源码的方式 OpenHarmony 主干代码获取 方式一&#xff08;推荐&am…

STL常用容器整理

STL常用容器操作整理 STL常用容器操作整理&#xff08;string/vector/set/map&#xff09;一、string&#xff08;字符串&#xff09;构造函数元素访问修改操作容量操作子串与查找 二、vector&#xff08;动态数组&#xff09;构造函数元素访问修改操作容量操作 三、set&#x…

Unity 实现伤害跳字

核心组件&#xff1a; Dotween TextMeshPro 过程轨迹如下图&#xff1a; 代码如下&#xff1a; using System.Collections; using System.Collections.Generic; using DG.Tweening; using TMPro; using UnityEngine; using UnityEngine.Pool;public class …

Ubuntu 22.04 AI大模型环境配置及常用工具安装

一、基础环境准备 1.1 系统准备 建议使用 Ubuntu22.04 以下配置皆以 Ubuntu22.04 系统版本为例 1.2 安装git apt-get update && apt-get install git -y1.3 安装 Python 3.9 【建议安装 3.10】&#xff08;安装miniconda或者conda来管理虚拟环境&#xff09; wget …