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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板)

=========================================================================

相关代码gitee自取

C语言学习日记: 加油努力 (gitee.com)

 =========================================================================

接上期

【C++初阶】七、内存管理
(C/C++内存分布、C++内存管理方式、operator new / delete 函数、定位new表达式)
-CSDN博客

 =========================================================================

                     

目录

             

一 . 泛型编程


二 . 函数模板

函数模板的概念

函数模板的格式

函数模板的原理

函数模板的实例化

隐式实例化:

显式实例化:

模板参数的匹配原则


三 . 类模板

类模板的定义格式

类模板的实例化

图示 --  以栈类为例:


本篇博客相关代码

Test.cpp文件 -- C++文件

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

一 . 泛型编程

                 

  • 我们以前写的函数一般都是针对某种类型实现两值交换Swap函数

    如果交换的两值int类型那就要将Swap函数参数设置为int类型

    如果交换的两值double类型那就要将Swap函数参数设置为double类型……
    通过函数重载实现
                      

  • 对于函数虽然函数重载可以实现函数参数多类型的问题
    但也有一些不好的地方
    1、重载的函数仅仅是类型不同而已具体实现实现逻辑都是很类似
    当接收的函数参数类型不同就需要用户自己增加对应的重载函数
    2、代码可维护性比较其中一个重载函数出错可能所有的重载函数都会出错
                           

  • 那能不能实现一个通用的Swap函数实现泛型编程
    泛型编程 -- 编写与类型无关的通用代码代码复用的一种手段
    C++中为解决这个问题有了模板的概念模板泛型编程的基础
                      
  • 有了模板,相当于告诉编译器一个模子
    编译器能够根据不同的类型利用该模子生成对应类型的代码

    模板分为函数模板类模板
图示:

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

二 . 函数模板

函数模板的概念

                   

函数模板代表了一个函数家族该函数模板与类型无关

在使用时被参数化根据实参类型产生函数的特定类型版本

                     

                     


                    

函数模板的格式

              

  • 注意
    typename是用来定义模板参数的关键字上面的T1T2Tn就是模板参数),
    除了可以使用typename来定义还可以使用class来定义

    //函数模板格式:
    template<typename T1, typename T2, ……, typename Tn>
    函数返回值类型 函数名(参数列表)
    {// 函数体
    }
图示:

                     

                     


                    

函数模板的原理

            

  • 函数模板是一个蓝图它本身并不是函数
    编译器使用后能产生特定具体类型函数摸具
    所以模板就是将本来应该由我们完成的重复的事情交给了编译器完成
                   
  • 编译器编译阶段对于函数模板的使用
    编译器需要根据传入的实参类型推演生成对应类型的函数以供调用
    比如
    当使用double类型调用函数模板编译器通过对实参类型推演
    模板参数T确定为double类型然后产生一份专门处理double类型的代码
图示:

                     

                     


                    

函数模板的实例化

                   

不同类型的参数调用模板称为函数模板的实例化
模板参数实例化分为隐式示例化显式实例化
               

                   

隐式实例化:

                       

  • 编译器根据实参推演模板参数的实际类型
    上面的图示中的模板参数实例化都是隐式实例化
图示:

                   

  • 隐式实例化
    如果只设置了一个模板参数实参中却有多种类型这时将不能通过编译
    此时有两种处理方式
    1、用户自己来强制转化2、使用显式实例化
图示:

                     

                       

---------------------------------------------------------------------------------------------

                  

显式实例化:

               

  • 不通过模板参数推演识别出实参的类型而是自己显式设置模板参数的类型
    函数名后的<>指定模板参数的实际类型即可
                   
  • 显式实例化如果类型不匹配编译器会尝试进行隐式类型转换
    如果无法转换成功编译器将会报错
                       
  • 显式实例化真正用法
    设置了一个模板函数参数中并没有设置模板参数
    函数体中却使用了模板参数类型或者返回值模板参数类型
    这种情况就需要显式实例化确定实参类型
图示:

                     

                     


                    

模板参数的匹配原则

                     

  • 一个非模板函数可以和一个同名的函数模板同时存在
    而且该函数模板还可以被实例化为这个非模板函数
图示:

                

  • 对于非模板函数同名函数模板如果其它条件都相同
    在调动时会优先调用非模板函数不会从该模板产生出一个示例
    如果模板可以产生一个具有更好匹配的函数那么将选择模板
图示:

                   

  • 模板函数不允许自动类型转换普通函数可以进行自动类型转换

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

三 . 类模板

类模板的定义格式

                 

  • 类模板定义函数模板定义类似定义时将函数的位置换成类即可
    模板参数类型类中定义成员类型时进行使用

    //类模板定义格式:
    template<class T1, class T2, ……, class Tn>
    class 类模板名
    {    // 类内成员定义    
    }

                     


                    

类模板的实例化

                

  • 类模板实例化函数模板实例化不同类模板实例化需要在类模板名字后跟<>
    然后将实例化的类型放在<>即可
                        
  • 类模板名字不是真正的类名显式实例化后的结果才是真正的类名
              
  • 同一个类模板显式实例化出的不同类这些类的类型不一样
    栈类模板为例
    Stack<int> st1 Stack<double> st2
    st1 的类型是 Stack<int> ,是用于存储int类型数据
    st2 的类型是 Stack<double> ,是用于存储double类型数据
    st1 st2 类型不一样
图示 --  以栈类为例:

            

  • 注意
    类模板成员函数的声明和实现分离不能分离到两个文件中
    分离时通常都写在一个.h文件
    而且分离后的成员函数实现部分需要设置对应的函数模板
    分离后不指定成员函数的类域而是指定其类模板类型
图示:

         

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

             

本篇博客相关代码

Test.cpp文件 -- C++文件:

#define _CRT_SECURE_NO_WARNINGS 1//包含IO流:
#include <iostream>;
//完全展开std命名空间:
using namespace std;//Swap函数 -- 交换两个int类型数据:
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}//Swap函数 -- 交换两个double类型数据:
void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}//Swap函数 -- 交换两个char类型数据:
void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}/*
* 这里实现了三个Swap函数,
* 分别交换了三种不同的类型,
* 但实现的逻辑都是相同的,就只有交换类型不同,
* 所以就造成了某种程度的“冗余”
* 
* 上面的函数都需要针对具体的类型,
* 那能不能让一个代码能够针对广泛的类型呢,
* C++中就有了泛型编程:
*///函数模板:
template<typename T>
//tyename 也可以写成 class
//template<class T> 
//Swap函数 -- 交换两类型数据(泛型编程):
void Swap(T& left, T& right)
{char temp = left;left = right;right = temp;
}
/*
* 使用函数模板即可实现泛型编程,
* 让函数能够针对广泛的类型,
* 而不只能针对一种类型,
* 
* 通过关键字template即可定义一个模板,
* Swap函数的参数设置为模板参数
*///主函数:
int main()
{int a = 0; //int类型变量int b = 1; //int类型变量double c = 1.1; //double类型变量double d = 2.2; //double类型变量//调用设置了模板参数的Swap函数:Swap(a, b); //int类型 -- 模板参数TSwap(c, d); //double类型 -- 模板参数T/** 这里调用的两个Swap函数实际不是同一个,* 两个Swap函数的函数地址不同,* 不同类型调用的Swap函数不同是由模板参数导致的* *			模板的原理:* 模板参数接受参数如果是int类型,* 需要调用到int类型的函数,* T 模板参数就会推演成 int类型,(模板参数推演)* 然后就会实例化出具体的函数:* T 是int类型的对应函数。(模板实例化)* * 如果接收的是double类型数据,* T 模板参数就会推演成 double类型,(模板参数推演)* 然后就会示例化出具体的函数:* T 是double类型的对应函数。(模板实例化)*/return 0;
}//如果一个函数需要接收不同类型的参数:
template<class T1, class T2>
/*
* 如果需要接收不同类型的参数,
* 直接在模板中设置多个模板参数即可,
*(模板参数名可以随便取,但一般会取为T -- type)
* 
* 模板参数 和 函数参数 类似,
* 但是 函数参数 定义的是 形参对象,
* 而 模板参数 定义的则是 类型
*/
void func(const T1& t1, const T2& t2)
//模板参数T1接收一种类型,T2接收另一种类型
{cout << t1 << endl;cout << t2 << endl;/** 设置了模板参数的函数,* 如果要进行输入或输出,* 就必须使用 cin/cout 进行 输入/输出 了,* 因为设置了模板参数,* 不知道实际传进来的数据是什么数据,* 因为使用 scanf/printf 必须要指定数据类型,* 所以这里使用 scanf/printf 来 输入/输出*/
}//通用(泛型)加法函数:
template<class T>
T Add(T left, T right)
//接收 T 模板参数类型
{return left + right;//返回值也是 T 模板类型
}template<class T>
T* f()
{//开辟T类型的动态空间:T* p = new T[10];//没设置模板参数T,却使用了T//返回T类型指针:return p;/** 该函数没有设置模板参数T,* (设置的参数不是模板参数)* 但返回值却返回模板指针类型(T*),* * 没设置模板参数就无法进行类型推演*/
}//主函数:
int main()
{/**			推演实例化:* 函数参数传递,推演出模板参数的类型,* 再生成(实例化)对应的函数*///隐式实例化://T1推演为int,T2推演为int:func(1, 2);//T1推演为double,T2推演为double:func(1.1, 2.2);//T1推演为double,T2推演为int:func(1.1, 2);//调用通用(泛型)加法函数:cout << Add(1, 2.2) << endl;/** 该语句不能通过编译,因为在编译期间,* 当编译器看到该实例化时,需要推演其实参类型* 通过实参a1将T推演为int,通过实参d1将T推演为double类型,* 但模板参数列表中只有一个T,* 编译器无法确定此处到底该将T确定为int 或者 double类型而报错* * 注意:在模板中,编译器一般不会进行类型转换操作,* 因为一旦转化出问题,编译器就需要背黑锅* * 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化*/	cout << Add(1, (int)2.2) << endl;//显式实例化:// 2.2 隐式转换为int类型:cout << Add<int>(1, 2.2) << endl; // 1 隐式转换为double类型:cout << Add<double>(1, 2.2) << endl;/** 直接显式实例化,指定将参数实例化为某种类型,* 而不通过模板参数的类型推演*///函数没有设置模板参数:double* p = f<double>();/** 函数参数没设置模板参数,* 但却使用了模板参数,* 编译器没法进行类型推演,* 所以此时就需要显式实例化来确定类型* (显式实例化的真正用法)*/return 0;
}//使用栈解决多类型问题:
typedef int STDataType;
/*
* 想让栈存储int类型数据,
* 就在这里设置类型为int,
* 想让栈存储double类型数据,
* 就在这里设置类型为double,
* ……
*/类模板:
//template<class T>
//
类模板 -- 栈类:
//class Stack
//{
//public: //公有成员函数:
//
//	//构造函数:
//	Stack(int capacity = 4)
//	{
//		//调用了构造函数则打印:
//		cout << "Stack(int capacity = 4)" << endl;
//
//		//使用new开辟栈容量大小的空间:
//		
//		// typedef 设置多类型:
//		//_a = new STDataType[capacity];
//
//		// 类模板 设置多类型:
//		_a = new T[capacity]; //使用模板T类型
//
//		_top = 0; //栈顶值默认为0
//		_capacity = capacity; //设置栈容量
//	}
//
//	//析构函数:
//	~Stack()
//	{
//		//调用了析构函数则打印:
//		cout << "~Stack()" << endl;
//
//		//使用delete释放new开辟的空间:
//		delete[] _a;
//
//		_a = nullptr; //置为空指针
//		_top = 0; //栈顶值置为0
//		_capacity = 0; //栈容量置为0
//	}
//
//private: //私有成员变量:
//
//	T* _a; //栈指针 -- 使用模板T类型
//	int _top; //栈顶值
//	int _capacity; //栈容量
//
//};//类模板:
template<class T>//类模板 -- 栈类:
class Stack
{
public: //公有成员函数://构造函数 -- 类模板成员函数声明和定义分离:Stack(int capacity = 4);//析构函数:~Stack(){//调用了析构函数则打印:cout << "~Stack()" << endl;//使用delete释放new开辟的空间:delete[] _a;_a = nullptr; //置为空指针_top = 0; //栈顶值置为0_capacity = 0; //栈容量置为0}private: //私有成员变量:T* _a; //栈指针 -- 使用模板T类型int _top; //栈顶值int _capacity; //栈容量 };//类模板成员函数的声明和实现分离:
template<class T>
Stack<T>::Stack(int capacity)
/*
* 实现时指定的不是Stack成员函数的类名(类域),
* 而是Stack成员函数的类型,
* (不是Stack::,而是Stack<T>)
* 需要把模板参数写出来
* 
*				注:
* 类模板不允许声明和定义分离到两个文件,
* 分离时都写在一个.h文件中
*/
{//调用了构造函数则打印:cout << "Stack(int capacity = 4)" << endl;//使用new开辟栈容量大小的空间:// typedef 设置多类型://_a = new STDataType[capacity];// 类模板 设置多类型:_a = new T[capacity]; //使用模板T类型_top = 0; //栈顶值默认为0_capacity = capacity; //设置栈容量
}//主函数:
int main()
{/** typedef 可以解决多类型问题,* 那 typedef 可以代替 模板 吗?* * 答案是不能,typedef设置一个类的类型后,* 该类的类型就只能是typedef设置的那一种了,* * 如果用类模板的话设置一个类的话,* 该类的一个对象就可以是int类型,* 而该类的另一个对象还可以是double类型*///显式实例化://让这个栈类型对象存储int类型:Stack<int> st1; //int//让这个栈类型对象存储double类型:Stack<double> st2; //double/** 函数模板可以显式实例化,也可以让它自己推演,* 函数模板大多数情况让它自己推演出类型,* 不进行显式实例化* * 类模板能让一个类的对象是不同类型的,* (如:都是栈类对象,但一个栈对象存储int类型数据,* 另一个栈对象存储double类型数据)* 只需要在创建对象时显式实例化需要的类型即可。* 这时我们实现的数据结构,* 就跟具体的存储类型是无关的,想要哪种类型,* 在创建对象时就显式实例化哪种类型*/return 0;
}// 专门处理int的加法函数 -- 非模板函数
int Add(int left, int right)
{return left + right;
}// 通用加法函数 -- 模板函数
template<class T>
T Add(T left, T right)
{return left + right;
}//测试函数:
void Test()
{// 与非模板函数匹配,编译器不需要特化:Add(1, 2); // 调用编译器特化的Add版本:Add<int>(1, 2); //函数模板Add被实例化为非模板函数Add
}//专门处理int的加法函数 -- 非模板函数
int Add(int left, int right)
{return left + right;
}//通用加法函数 -- 模板函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{return left + right;
}//测试函数:
void Test()
{//Add(int, int):Add(1, 2);/** 与非函数模板类型完全匹配,* 不需要函数模板实例化*///Add(int, double):Add(1, 2.0);/** 模板函数可以生成更加匹配的版本,* 编译器根据实参生成更加匹配的Add函数*/
}

相关文章:

【C++初阶】八、初识模板(泛型编程、函数模板、类模板)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【C初阶】七、内存管理 &#xff08;C/C内存分布、C内存管理方式、operator new / delete 函数、定位new表达式&#xff09; -CSDN博客 目录 一 . 泛型编程 二 . 函数模板 函数模板…...

珠海数字孪生赋能工业智能制造,助力制造业企业数字化转型

珠海数字孪生赋能工业智能制造&#xff0c;助力制造业企业数字化转型。数字孪生是利用物理模型、传感器更新及运行历史数据&#xff0c;集成多物理量、多尺度的仿真过程。巨蟹数科数字孪生通过构建物理车间与虚拟车间之间的有效映射并实时反馈机制&#xff0c;实现物理车间与虚…...

HarmonyOS开发实战:如何实现一个运动排名榜页面

HarmonyOS开发实战&#xff1a;如何实现一个运动排名榜页面 代码仓库&#xff1a; 运动排名榜页面 项目介绍 本项目使用声明式语法和组件化基础知识&#xff0c;搭建一个可刷新的排行榜页面。在排行榜页面中&#xff0c;使用循环渲染控制语法来实现列表数据渲染&#xff0c;…...

2019年第八届数学建模国际赛小美赛D题安全选举的答案是什么解题全过程文档及程序

2019年第八届数学建模国际赛小美赛 D题 安全选举的答案是什么 原题再现&#xff1a; 随着美国进入一场关键性的选举&#xff0c;在确保投票系统的完整性方面进展甚微。2016年总统大选期间&#xff0c;唐纳德特朗普因被指控受到外国干涉而入主白宫&#xff0c;这一问题再次成为…...

vivado 创建实施约束

创建实施约束 在您有了一个合成的网表之后&#xff0c;您可以将它与XDC文件一起加载到内存中&#xff0c;或者Tcl脚本已启用以进行实现。当加载XDC以便验证和更正任何不能应用的约束。在某些情况下&#xff0c;合成网表中的对象名称与精心设计。如果是这种情况&#xff0c;则必…...

【代码分析】MPI

代码解读 问题 model/AdaMPI.py:21 为什么下降分辨率model.CPN.unet.FeatMaskNetwork 为什么用的是mask&#xff0c;unet&#xff1f; MPI class MPIPredictor(nn.Module):def __init__(self,width384,height256,num_planes64,):super(MPIPredictor, self).__init__()self.…...

数字孪生Web3D智慧机房可视化运维云平台建设方案

前言 进入信息化时代&#xff0c;数字经济发展如火如荼&#xff0c;数据中心作为全行业数智化转型的智慧基座&#xff0c;重要性日益凸显。与此同时&#xff0c;随着东数西算工程落地和新型算力网络体系构建&#xff0c;数据中心建设规模和业务总量不断增长&#xff0c;机房管理…...

飞天使-docker知识点12-docker-compose

文章目录 docker-compose命令启动单个容器重启容器停止和启动容器停止和启动所有容器演示一个简单示范 docker-compose 部署有依赖问题 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它允许您使用简单的 YAML 文件来配置应用程序的服务、网络和存储等方…...

快速排序(一)

目录 快速排序&#xff08;hoare版本&#xff09; 初级实现 问题改进 中级实现 时空复杂度 高级实现 三数取中 快速排序&#xff08;hoare版本&#xff09; 历史背景&#xff1a;快速排序是Hoare于1962年提出的一种基于二叉树思想的交换排序方法 基本思想&#xff1a…...

GO的sql注入盲注脚本

之间学习了go的语法 这里就开始go的爬虫 与其说是爬虫 其实就是网站的访问如何实现 因为之前想通过go写sql注入盲注脚本 发现不是那么简单 这里开始研究一下 首先是请求网站 这里貌似很简单 package mainimport ("fmt""net/http" )func main() {res, …...

写好ChatGPT提示词原则之:清晰且具体(clear specific)

ChatGPT 的优势在于它允许用户跨越机器学习和深度学习的复杂门槛&#xff0c;直接利用已经训练好的模型。然而&#xff0c;即便是这些先进的大型语言模型也面临着上下文理解和模型固有局限性的挑战。为了最大化这些大型语言模型&#xff08;LLM&#xff09;的潜力&#xff0c;关…...

Java实现快速排序及其动图演示

快速排序&#xff08;Quicksort&#xff09;是一种基于分治思想的排序算法。它通过选择一个基准元素&#xff0c;将数组分为两个子数组&#xff0c;其中一个子数组的所有元素都小于基准元素&#xff0c;另一个子数组的所有元素都大于基准元素&#xff0c;然后递归地对这两个子数…...

iClient3D 图元操作

1. S3MTilesLayer&#xff0c;S3M(Spatial 3D Model)图层类 S3MTilesLayer&#xff0c;S3M(Spatial 3D Model)图层类&#xff0c;通过该图层实现加载三维切片缓存&#xff0c;包括倾斜摄影模型、BIM模型、点云数据、精细模型、矢量数据、符号等。 那S3MTilesLayer中针对图元的…...

从0到1!开发小白快速入门腾讯云数据库

在这个海量数据大爆发的时代&#xff0c;一个单一的开源数据库产品往往很难直接满足企业的业务需求&#xff0c;在某些场景下&#xff0c;无论是性能、安全还是稳定性&#xff0c;都面临着各种各样的问题。 你在工作中也有这样的烦恼的话&#xff0c;一定是因为你还没有使用过…...

Golang清晰代码指南

发挥易读和易维护软件的好处 - 第一部分 嗨&#xff0c;开发者们&#xff0c;清晰的代码是指编写易于阅读、理解和维护的软件代码。它是遵循一组原则和实践&#xff0c;优先考虑清晰性、简单性和一致性的代码。清晰的代码旨在使代码库更易管理&#xff0c;减少引入错误的可能性…...

C语言 文件I/O(备查)

所有案列 跳转到其他。 文件打开 FILE* fopen(const char *filename, const char *mode); 参数&#xff1a;filename&#xff1a;指定要打开的文件名&#xff0c;需要加上路径&#xff08;相对、绝对路径&#xff09;mode&#xff1a;指定文件的打开模式 返回值&#xff1a;成…...

web(HTML之表单练习)

使用HTML实现该界面&#xff1a; 要求如下&#xff1a; 用户名为文本框&#xff0c;名称为 UserName&#xff0c;长度为 15&#xff0c;最大字符数为 20。 密码为密码框&#xff0c;名称为 UserPass&#xff0c;长度为 15&#xff0c;最大字符数为 20。 性别为两个单选按钮&a…...

通过对象轮换实现 LRU 缓存结构

文章目录 通过两个对象轮换&#xff0c;按照是否访问实现内容长久保存rollup 的缓存实现 export default function (max) { //max 缓存容量var num, curr, prev;var limit max || 1;function keep(key, value) {if (num > limit) {prev curr; // 超过容量时当前对象变成缓…...

【Unity动画】综合案例完结-控制角色动作播放+声音配套

这个案例实现的动作并不复杂&#xff0c;主要包含一个 跳跃动作、攻击动作、还有一个包含三个动画状态的动画混合树。然后设置三个参数来控制切换。 状态机结构如下&#xff1a; 完整代码 using System.Collections; using System.Collections.Generic; using UnityEngine;pu…...

【工作流Activiti】任务组

1、Candidate-users候选人 1.1、需求 在流程定义中在任务结点的assignee固定设置任务负责人&#xff0c;在流程定义时将参与者固定设置在.bpmn文件中&#xff0c;如果要临时变更任务负责人则需要修改流程定义&#xff0c;系统扩展性很差&#xff0c;针对这种情况&#xff0c;我…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

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

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

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...

DAY 45 超大力王爱学Python

来自超大力王的友情提示&#xff1a;在用tensordoard的时候一定一定要用绝对位置&#xff0c;例如&#xff1a;tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾&#xff1a; tensorboard的发展历史和原理tens…...