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

这篇具有很好参考价值的文章主要介绍了【C++初阶】八、初识模板(泛型编程、函数模板、类模板)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

相关代码gitee自取

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

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

接上期

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

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

                     

目录

             文章来源地址https://www.toymoban.com/news/detail-760268.html

一 . 泛型编程


二 . 函数模板

函数模板的概念

函数模板的格式

函数模板的原理

函数模板的实例化

隐式实例化:

显式实例化:

模板参数的匹配原则


三 . 类模板

类模板的定义格式

类模板的实例化

图示 --  以栈类为例:


本篇博客相关代码

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

         

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

             

一 . 泛型编程

                 

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

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

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

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

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

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

         

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

             

二 . 函数模板

函数模板的概念

                   

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

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

                     

                     


                    

函数模板的格式

              

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

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                     

                     


                    

函数模板的原理

            

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                     

                     


                    

函数模板的实例化

                   

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

                   

隐式实例化:

                       

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                   

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                     

                       

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

                  

显式实例化:

               

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                     

                     


                    

模板参数的匹配原则

                     

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

                   

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

         

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

             

三 . 类模板

类模板的定义格式

                 

  • 类模板定义函数模板定义类似定义时将函数的位置换成类即可
    模板参数类型类中定义成员类型时进行使用
    //类模板定义格式:
    template<class T1, class T2, ……, class Tn>
    class 类模板名
    {    
        // 类内成员定义    
    }

                     


                    

类模板的实例化

                

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

            

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

【C++初阶】八、初识模板(泛型编程、函数模板、类模板),CCC全是C,c++,开发语言,visualstudio

         

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

             

本篇博客相关代码

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类型 -- 模板参数T
	Swap(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++初阶】八、初识模板(泛型编程、函数模板、类模板)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • C++ 泛型编程:函数模板

    C++ 泛型编程:函数模板

    当需要编写通用的代码以处理不同类型的数据时,C++ 中的函数模板是一个很有用的工具。函数模板允许我们编写一个通用的函数定义,可以用于多种不同的数据类型,从而提高代码的重用性和灵活性。 泛型编程 是一种编程范式,旨在实现可重用、通用性高的代码。它允许我

    2024年02月12日
    浏览(9)
  • 【C++】泛型编程 ② ( 函数模板与普通函数区别 )

    【C++】泛型编程 ② ( 函数模板与普通函数区别 )

    函数模板与普通函数区别 : 主要区别在于它们能够处理的 数据类型数量 和 灵活性 ; 自动类型转换 : 函数模板 不允许 自动类型转化 , 会进行严格的类型匹配 ; 普通函数 能够进行 自动类型转换 , 内含隐式的类型转化 ; 参数 / 返回值 数据类型 : 普通函数 只接受 特定类型 参数

    2024年02月20日
    浏览(9)
  • 【C++】泛型编程 ③ ( 函数模板 与 普通函数 调用规则 | 类型匹配 | 显式指定函数模板泛型类型 )

    【C++】泛型编程 ③ ( 函数模板 与 普通函数 调用规则 | 类型匹配 | 显式指定函数模板泛型类型 )

    上一篇博客 【C++】泛型编程 ② ( 函数模板与普通函数区别 ) 中 , 分析了 函数参数 类型匹配 下的 普通函数 与 函数模板 的调用规则 ; 为 函数模板 重载了 普通函数 , 普通函数有指定的类型 ; 传入实参 , 调用 普通函数 还是 模板函数 , 是有一定的规则的 ; 普通函数 与 传入实

    2024年02月21日
    浏览(10)
  • 【C++】泛型编程 ① ( 函数模板 | 函数模板概念 | 函数模板意义 | 函数模板定义语法 | 函数模板调用语法 | 显式类型调用 | 自动类型推导 )

    【C++】泛型编程 ① ( 函数模板 | 函数模板概念 | 函数模板意义 | 函数模板定义语法 | 函数模板调用语法 | 显式类型调用 | 自动类型推导 )

    在 C++ 语言中 , 泛型编程 的 核心就是 函数模板 和 类模板 ; 函数模板 Function Template 是 C++ 语言 中的 重要特性 ; 函数模板概念 : 建立一个 \\\" 通用函数 \\\" , 不指定该函数的 函数返回值类型 和 函数参数类型 , 仅使用 \\\" 虚拟类型 \\\" 代表 上述 两种类型 , 该 \\\" 通用函数 \\\" 就是 \\\" 函数模

    2024年02月19日
    浏览(8)
  • C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数(侯捷)

    C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数(侯捷)

    侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! ! 一、C++ 面向对象高级开发 1、C++面向对象高级编程(上) 2、C++面向对象高级编程(下) 二、STL 标准库和泛型编程 1、分配器、序列式容器 2、关联式容器 3、迭代器、 算法、仿函数 4、适配器、补充 三、C++ 设计模式 四、C++ 新标准 五、

    2023年04月25日
    浏览(15)
  • 【C++初阶】内存管理 && 初识模板

    【C++初阶】内存管理 && 初识模板

    C/C++的内存分布主要分为 栈区、堆区、数据段和代码段,还有内存映射段。 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。

    2024年02月04日
    浏览(8)
  • C++泛型编程之模板

    C++泛型编程之模板

    目录 一、什么是泛型编程  二、函数模板 2.1函数模板的概念 2.2函数模板格式 2.3函数模板的原理  2.5函数模板的实例化 2.6模板参数的匹配原则 三、类模板 3.1类模板的定义格式 3.2 类模板的实例化 四、非类型模板参数 五、模板的特化 5.1模板特化的概念: 5.2函数模板特化 5

    2024年02月07日
    浏览(10)
  • 【C++】泛型编程——模板进阶

    【C++】泛型编程——模板进阶

    在之前的文章里,我们进行了模板初阶的学习( 【C++】泛型编程——模板初阶),了解了什么是泛型编程,学习了函数模板和类模板。 那这篇文章,我们继续学习模板进阶的内容的学习。 首先我们来回顾一下: 我们在模板初阶的学习中,定义模板参数是怎么定义的? 是不

    2024年02月16日
    浏览(10)
  • 【C++】模板初阶——函数模板和类模板

    【C++】模板初阶——函数模板和类模板

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🚁 个人主页:不 良 🔥 系列专栏:🛸C++  🛹Linux 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同

    2024年02月10日
    浏览(9)
  • 【c++ primer 笔记】第 16章 模板与泛型编程

    【c++ primer 笔记】第 16章 模板与泛型编程

    🎉作者简介:👓 博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢 c + + , g o , p y t h o n , 目前熟悉 c + + , g o 语言,数据库,网络编程,了解分布式等相关内容 textcolor{orange}{博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c+

    2024年02月20日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包