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

C++《类和对象》(上)

在之前的C++入门基础知识中我们了解了C++的发展过程已经重要性,还初步了解了C++中一些相比C语言特有的知识点,例如命名空间、缺少参数、函数重载、引用等,接下来在本篇中我们将开始C++整个体系中非常重要的一个知识章节——类和对象,类和对象时之后我们更加深入学习C++所必须要学习的,可见其重要性,这其中有一些内容是难以理解的,需要我们花较为多的时间和精力,一起加油吧!!!


1.类的定义

1.1 类定义格式

在 C++ 中,类是一种用户自定义的数据类型,它封装了一组相关的数据成员(也称为属性)和成员函数(也称为方法)。

在类的定义中要用到关键字class,要定义一个类需要在关键字class后定义一个类名,之后{}中为类的主体,注意类定义结束时后面分号不能省略。

例如以下就是一个类

#include<iostream>;
using namespace std;class Stack
{// 成员函数void Init(int n = 4){_array = (int*)malloc(sizeof(int) * n);if (nullptr == _array){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}void Destroy(){free(array);_array = nullptr;_top = _capacity = 0;}// 成员变量int* _array;int _capacity;int _top;
}; // 分号不能省略

在以上的类Stack中就可以看出在类中是有成员函数的,这和之前我们在C语言中结构体中不同,在结构体中的只能含有成员变量,而在类中既可以有成员变量也可以有成员函数
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。

在以上的类还有看出在成员变量前面都加_,这是为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加_ 或者 m开头,注意C++中这个并不是强制的,只是⼀些惯例。

注:定义在类里面的成员函数默认为inline。

其实在C++中除了可以用class来定义类,struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类,明显的变化是struct中可以定义函数,⼀般情况下我们还是推荐用class定义类。

C++中的struct相比C语言中的会有以下额外的特点:
1、类里面可以定义函数
2、struct名称就可以代表类型

#include<iostream>;
using namespace std;typedef struct ListNodeC
{struct ListNodeC* next;int val;
}LTNode;
// 不再需要typedef,ListNodeCPP就可以代表类型
struct ListNodeCPP
{void Init(int x){next = nullptr;val = x;}ListNodeCPP* next;int val;
};

 1.1.2访问限定符

如果要在一个类当中让一些成员在类外可以直接被访问,一些成员不可以在类外访问要怎么做呢?

这时就要用到访问限定符,这是C++⼀种实现封装的方式,用类将对象的属性与方法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

访问限定符有以下三种:

public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访
问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。
 

访问权限作用域:从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 }即类结束。
注:class定义成员没有被访问限定符修饰时默认为private,struct默认为public。

以上的类就可以加上访问限定符

#include<iostream>;
using namespace std;class Stack
{
pubilc:// 成员函数void Init(int n = 4){_array = (int*)malloc(sizeof(int) * n);if (nullptr == _array){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}
private:	void Destroy(){free(array);_array = nullptr;_top = _capacity = 0;}// 成员变量int* _array;int _capacity;int _top;
}; // 分号不能省略

注:通常我们会将类内的⼀般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。

 1.1.3类域

在之前我们学习了命名空间域时已经知道C++中域有函数局部域,全局域,命名空间域,类域,接下来我们就来深入学习类域

类定义了⼀个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域

例如以下类:

class Stack
{
public:// 成员函数void Init(int n = 4);
private:// 成员变量int* _array;size_t _capacity;size_t _top;
};
// 声明和定义分离,需要指定类域
void Stack::Init(int n)
{_array = (int*)malloc(sizeof(int) * n);if (nullptr == _array){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;
}

以上程序中Init如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到array等成员的声明/定义在哪⾥,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。

 2.类实例化

2.1 实例化概念

用类类型在物理内存中创建对象的过程,称为类实例化出对象

之前我们进行类的定义,但类是对象进行⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间

一个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。打个比方:类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,设计图规划了有多少个房间,房间大小功能等,但是并没有实体的建筑存在,也不能住人,用设计图修建出房子,房子才能住人。同样类就像设计图⼀样,不能存储数据,实例化出的对象分配物理内存存储数据。

 例如以下就是在创建类Date后实例化出对象d1

#include<iostream>;using namespace std;class Date
{
public:void Init(int year, int mouth, int day){_year = year;_mouth = mouth;_day = day;}void Print(){cout << _year << "/" << _mouth << "/" << _day << endl;}private:
// 这⾥只是声明,没有开空间int _year;int _mouth;int _day;
};int main()
{
//实例化出对象d1Date d1;d1.Init(2024, 8, 11);d1.Print();return 0;
}

2.2对象大小

在学习了类相关的概念和实例化的概念后那么类的大小应该如何计算呢?接下来我们就来分析看看

首先要分析的是在计算类的大小时是只计算类中成员变量的大小还是成员变量和成员函数的大小都计算呢?


我们来通过之前创建的日期类Date来分析

class Date
{
public:void Init(int year, int mouth, int day){_year = year;_mouth = mouth;_day = day;}void Print(){cout << _year << "/" << _mouth << "/" << _day << endl;}private:
// 这⾥只是声明,没有开空间int _year;int _mouth;int _day;
};

在以上的类中当我们实例化出一个个新的对象时,因为每个实例化出的对象都有各自的成员变量_year,_mouth,_day,因此类实例化出的每个对象,都有独立的数据空间 ,如果要将成员函数也存储在内存空间内,存储的也就是函数指针,那么由于在每个实例化的对象内的成员函数都是相同的,这就会出现内存的浪费例如以上的类当实例化出100个对象时,如果成员函数是存储在对象当中,成员函数指针就重复存储100次

通过以上示例的分析可以得出在类的实例化中成员函数不是存储在对象的空间内的,而是独立存储的 ,因此在计算类的大小是不需要加上成员函数指针

上面我们分析了对象中只存储成员变量,C++规定类实例化的对象也要符合内存对齐的规则

在之前C语言的结构体类型章节我们学习了内存对齐的规则,因此在此就不再进行讲解

内存对齐规则
• 第⼀个成员在与结构体偏移量为0的地址处。
• 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
• 注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。
• VS中默认的对齐数为8
• 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
• 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

接下来来看以下代码 ,计算一下A/B/C实例化的对象是多大?

#include<iostream>
using namespace std;
// 计算⼀下A/B/C实例化的对象是多⼤?
class A
{
public:void Print(){cout << _ch << endl;}
private:char _ch;int _i;
};class B
{
public:void Print(){//...}
};class C
{};int main()
{A a;B b;C c;cout << sizeof(a) << endl;cout << sizeof(b) << endl;cout << sizeof(c) << endl;return 0;
}

 首先是类A的实例化a的存储会按以下形式

因此a大小为8字节 

 接下来是类B的实例化a和类C的示例化c中由于没有成员变量是否大小就为0字节呢?

其实没有成员变量的B和C类对象的大小是1,为什么没有成员变量还要给1个字节呢?因为如果一个字节都不给,怎么表示对象存在过呢!所以这里给1字节,纯粹是为了占位标识对象存在。
 

3.this指针

在以下代码中Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用Init和Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?这里面其实C++给了一个隐含的this指针解决这里的问题 

#include<iostream>;using namespace std;class Date
{
public:void Init(int year, int mouth, int day){_year = year;_mouth = mouth;_day = day;}void Print(){cout << _year << "/" << _mouth << "/" << _day << endl;}private:int _year;int _mouth;int _day;
};int main()
{Date d1;d1.Init(2024, 8, 11);d1.Print();Date d2;d2.Init(2024,8,12);d2.Print;return 0;
}

编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加一个当前类类型的指针,叫做this
指针
。比如Date类的Init的真实原型为, void Init(Date* const this, int year,int month, int day) 

类的成员函数中访问成员变量,本质都是通过this指针访问的 ,如Init函数中给_year赋值, this-
>_year = year;

注意:C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

因此实际上在以上的类Date内部的成员函数和main函数中是以下形式的

#include<iostream>;using namespace std;
class Date
{
public:
// void Init(Date* const this, int year, int month, int day)
//{
//	  this->_year = year;
//	  this->_mouth = mouth;
//	  this->_day = day;
//}void Init(int year, int mouth, int day){_year = year;_mouth = mouth;_day = day;}//void Print(Date* const this)
//{
//	cout << this->_year << "/" << this->_mouth << "/" << this->_day << endl;
//}void Print(){cout << _year << "/" << _mouth << "/" << _day << endl;}private:int _year;int _mouth;int _day;
};int main()
{Date d1;
//d1.Init(&d1,2024, 8, 11);d1.Init(2024, 8, 11);
//d1.Print(&d1);d1.Print();Date d2;
//d2.Init(&d2,2024,8,12);d2.Init(2024,8,12);
// d2.Print(&d2);d2.Print();return 0;
}

 

练习题

在了解完以上this指针相关的概念后,下面通过两个选择题测试⼀下

1.下面程序编译运行结果是()

A、编译报错 B、运行崩溃 C、正常运行

#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "A::Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}

 2.下面程序编译运行结果是()

A、编译报错 B、运行崩溃 C、正常运行

#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "A::Print()" << endl;cout << _a << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}

在上面两段代码中就只有在Print函数内有所不同,在第二段代码的Print函数内多输出了_a。在main函数内都是调用空指针p的Print函数,这时由于类中的成员函数的指针是在编译时确定的,不存储在对象里,因此这时不会引起对空指针的解引用,所以第一个程序能正常运行,第一题就选择C

而在第二个程序中在Print函数内的_a实际上是this->_a,这时因为_a是成员变量是存储在对象里的,这时这句代码就会造成对空指针的解引用,程序就会崩溃,因此第二个程序运行崩溃,第二题就选B

 

3. this指针存在内存哪个区域的 ()
A. 栈 B.堆 C.静态区 D.常量区 E.对象里面

为this指针是隐含的形参,因此在类当中this指针是类中成员函数的局部变量,我们之前就了解过局部变量是存储在栈区的,因此这题就选择A

 

4. C++和C语⾔实现Stack对比

⾯向对象三大特性:封装、继承、多态,下⾯的对比我们可以初步了解⼀下封装。
通过下面两份代码对比,我们发现C++实现Stack形态上还是发生了挺多的变化,底层和逻辑上没啥变化。

• C++中数据和函数都放到了类里面,通过访问限定符进行了限制,不能再随意通过对象直接修改数据,这是C++封装的⼀种体现,这个是最重要的变化。这里的封装的本质是⼀种更严格规范的管理,避免出现乱访问修改的问题。当然封装不仅仅是这样的,我们后面还需要不断的去学习。
• C++中有⼀些相对方便的语法,比如Init给的缺省参数会方便很多,成员函数每次不需要传对象地址,因为this指针隐含的传递了,方便了很多,使用类型不再需要typedef用类名就很方便
• 在我们这个C++入门阶段实现的Stack看起来变了很多,但是实质上变化不大。等着我们后面看STL中的用适配器实现的Stack,大家再感受C++的魅力。

C语言实现Stack 

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}
void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{assert(ps);// 满了, 扩容if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;
}
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}
STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->a[ps->top - 1];
}
int STSize(ST* ps)
{assert(ps);return ps->top;
}
int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d\n", STTop(&s));STPop(&s);}STDestroy(&s);return 0;
}

 

C++实现Stack

#include<iostream>
#include<assert.h>
using namespace std;
typedef int STDataType;
class Stack
{
public:// 成员函数void Init(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}void Push(STDataType x){if (_top == _capacity){int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}_a = tmp;_capacity = newcapacity;}_a[_top++] = x;}void Pop(){assert(_top > 0);--_top;}bool Empty(){return _top == 0;}int Top(){assert(_top > 0);return _a[_top - 1];}void Destroy(){free(_a);_a = nullptr;_top = _capacity = 0;}
private:// 成员变量STDataType* _a;size_t _capacity;size_t _top;
};
int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);while (!s.Empty()){printf("%d\n", s.Top());s.Pop();}s.Destroy();return 0;
}

以上就是C++中《类和对象》(上)的全部内容了,接下来在《类和对象》(中)我们将继续学习类和对象相关的知识,未完待续……

相关文章:

C++《类和对象》(上)

在之前的C入门基础知识中我们了解了C的发展过程已经重要性&#xff0c;还初步了解了C中一些相比C语言特有的知识点&#xff0c;例如命名空间、缺少参数、函数重载、引用等&#xff0c;接下来在本篇中我们将开始C整个体系中非常重要的一个知识章节——类和对象&#xff0c;类和对…...

LLM大语言模型算法特训

百度 LLM&#xff08;Large Language Model&#xff09;大语言模型算法特训是一个深度学习领域的高级培训项目&#xff0c;专门设计用于训练和优化大规模语言模型的开发者和研究人员。本文将详细探讨LLM算法的基本原理、训练技术、应用领域以及参与者可以预期的学习收获和挑战。…...

Docker相关笔记

Docker笔记 1. Dockerfile编译构建docker Dockerfile 是一个文本文件&#xff0c;包含了构建 Docker 镜像的所有指令。 Dockerfile 常用的有如下关键字&#xff1a; FROM&#xff1a;指定基础镜像&#xff0c;后续定制操作都是基于这个基础镜像&#xff0c;比如&#xff1a; …...

前端技术day01-HTML入门

一、前端介绍 技术描述HTML用于构建网站的基础结构的CSS用于美化页面的&#xff0c;作用和化妆或者整容作用一样JS实现网页和用户的交互Vue主要用于将数据填充到html页面上的Element主要提供了一些非常美观的组件 二、工具软件 VsCode 在前端领域&#xff0c;有一个公认好用…...

Multisim 用LM358 运放模拟线性稳压器 - 运放输出饱和 - 前馈电容

就是拿运放搭一个可调的LDO 稳压器&#xff0c;类似下面这个功能框图里的感觉。本来应该非常简单&#xff0c;没什么好说的&#xff0c;没想到遇到了两个问题。 原理 - 理想运放 我用PNP 三极管Q2 作为输出&#xff0c;运放输出电压升高时&#xff0c;流过PNP 三极管BE 的电流变…...

宁德大屏第二版总结

碰到难点 1.wss 心跳机制 实现前端和后端双向绑定 只要后端发送了消息 前端通过全局总线去触发你想要的函数。 全局总线 vue3可以全局总线下一个mitt 新建一个eventBus.js import mitt from "mitt"; const eventBus mitt();export default eventBus; 然后wss…...

冥想第一千二百四十七天(1247)

1.今天上午带桐桐去游泳了&#xff0c;买了卡吉诺&#xff0c;吃过最好吃的甜点。推荐。还有鸡排。 2.回来后带着媳妇&#xff0c;先加油。去给丈母娘看腿&#xff0c;等丈母娘等了好久&#xff0c;还帮她推车。 3.回来后&#xff0c;在丈母娘家跑步。很舒服。家长麦田的香味。…...

基于光学动捕定位下的Unity-VR手柄交互

Unity VR 场景手柄交互实现方案 需求 在已创建好的 Unity VR 场景中&#xff0c;接入游戏手柄&#xff0c;通过结合动捕系统与 VRPN&#xff0c;建立刚体&#xff0c;实时系统获取到手柄的定位数据与按键数据&#xff0c;通过编写代码实现手柄的交互逻辑&#xff0c;实现手柄…...

php json_decode 带反斜杠字符串json解析

PHP json_decode 带反斜杠字符串json解析 今天再次遇到了json字符串中包含反斜杠的问题&#xff0c;记录下解决方法 在JSON字符串中&#xff0c;反斜杠\用作转义字符。当JSON_UNESCAPED_SLASHES选项被用于json_encode()函数时&#xff0c;不会在slashes前面添加反斜杠。 但是…...

【NLP】文本张量表示方法【word2vec、词嵌入】

文章目录 1、文本张量表示2、one-hot词向量表示2.1、one-hot编码代码实现&#xff1a;2.2、onehot编码器的使用2.3、one-hot编码的优劣势 3、word2vec模型3.1、模型介绍3.2、CBOW模式3.3、skipgram模式3.4、word2vec的训练和使用3.4.1、获取训练数据3.4.2、训练词向量3.4.3、查…...

疯狂Java讲义_08_泛型

文章目录 泛型的传参若函数里的参数使用基类接受所有的派生类&#xff0c;怎么做&#xff1f; 类型通配符的上限类型通配符的下限 泛型的传参 注意 若类 Base 是类 Derived 的基类&#xff08;父类&#xff09;&#xff0c;那么数组类型 Base[] 是 Derived[] 的基类&#xff0…...

HCIA、OSPF笔记

一、OSI参考模型 1、OSI的结构 应用层&#xff1a;把人类语言转化成编码&#xff0c;为各种应用程序提供网络服务。 表示层&#xff1a;定义一些数据的格式&#xff0c;&#xff08;对数据进行加密、解密、编码、解码、压缩、解压缩&#xff0c;每一层都可以实现&#xff0c…...

Python删除lru_cache缓存

在 Python 中,lru_cache 是一个装饰器,用于添加缓存功能以提高函数的性能。如果你想清除或者删除 lru_cache 中的缓存,有几种方法可以做到: 手动清除缓存: lru_cache 对象有一个方法叫做 cache_clear(),可以手动清除所有缓存。示例:@lru_cache(maxsize=128) def some_fun…...

Android面试必问题:大白文讲透Android View工作原理

目录 第一章 引言 第二章 Android View 基础概念 2.1 视图(View) 2.2 布局(Layout) 2.3 绘制(Drawing) 第三章 Android View 工作原理详解 3.1 测量过程剖析 3.2 布局流程探究 第四章 Android View 性能优化建议 4.1 视图层级优化 4.2 避免过度的视觉效果 4.…...

WinDbg配置远程调试

WinDbg配置远程调试 1、为什么需要远程调试 某些特殊的场合需要远程调试&#xff0c;如&#xff1a; ①调试特殊的程序&#xff0c;比如在调试全屏程序&#xff0c;内核。 ②需要别人帮助调试或者帮助别人调试。比如由于商业性质不能直接给你pdb和源代码。 ③还有一类就是…...

spl注入实战thinkphp

目录 一、环境的部署 二、本地创建数据库 三、填写数据库连接文件 四、编写控制器 五、访问分析 debug报错会显示物理路径 原因是config.php文件相关配置 六、注入分析 七、进入断点调试 八、通过mysql执行语句查看结果 九、总结&#xff1a; 一、环境的部署 二、本地…...

整理深度学习时最常用的Linux命令(自用)

清华大学镜像源&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple/tar文件解压 tar -xzvf xxx.tar.gztar xvf xxx.tarzip文件解压 unzip xxx.zip -d path/to/your/fold清理GPU异常内存占用 杀掉 1 号显卡的所有进程 fuser -v /dev/nvidia1 | xargs -t -n 1 kill -9杀掉…...

LVS——>linux 虚拟服务器知识汇总

一、概念&#xff1a; LVS&#xff08;Linux Virtual Server&#xff09;&#xff0c;是Linux Virtual Server的简写&#xff0c;也就是Linux 虚拟服务器&#xff0c;是一个虚拟的服务器集群系统负载均衡解决方案&#xff0c;它将一个真实服务器集群虚拟成一台服务器来对外提供…...

AI赋能周界安防:智能视频分析技术构建无懈可击的安全防线

周界安全防范是保护机场、电站、油库、监狱、工业园区等关键设施免受非法入侵和破坏的重要措施。传统的周界安防手段主要依靠人员巡查和物理屏障&#xff0c;但这种方式不仅人力成本高&#xff0c;而且效率较低&#xff0c;难以满足日益复杂多变的安全需求。随着AI技术的引入&a…...

FastAPI+Vue3工程项目管理系统项目实战私教课 上课笔记20240808 课程和学习计划制定

学习目标 将Word和Excel做的东西放到数据库里面去工程类公司&#xff0c;甲方&#xff0c;劳务存到数据库存储的信息主要是人员的信息 基本信息&#xff1a; 人员信息&#xff0c;资料库&#xff0c;甲方的人出现在哪些项目上&#xff0c;考勤材料信息&#xff0c;进货记录&…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...