当前位置: 首页 > 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;进货记录&…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...