还在因为写项目函数太多而烦恼?C++模板一文带你解决难题

news2024/11/18 1:33:52

在这里插入图片描述

📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的
📖作者主页:热爱编程的小K
📖专栏链接:c++

🎉欢迎各位→点赞👏 + 收藏💞 + 留言🔔​
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾

在这里插入图片描述

💯文章目录

      • 💝一、什么是模板
      • 💖二、C++函数模板
      • 💓三、函数模板操作自定义类型
      • 💞四、C++类模板
      • 💕五、稍微复杂一点的类模板


💝一、什么是模板

模板是一种忽略数据的一种泛型编程。把数据当做未知量,当使用的时候传入类型的一种编程方式

语法

template <class T>//告诉编译器,接下来要用到一个未知类型是T类型
template <typename T>//等效class
template <class T1,class T2,class T3> //三个未知类型

#include<iostream>
#include<string>
using namespace std;
#if 0
int Max(int a, int b) 
{
	return a > b ? a : b;
}
float Max(float a, float b) 
{
	return a > b ? a : b;
}
double Max(double a, double b)
{
	return a > b ? a : b;
}
#endif
template <class T1> T1 Max(T1 a,T1 b)
{
	return a > b ? a : b;
}
int main() 
{
	cout << Max<int>(9, 10);
	return 0;
}

💖二、C++函数模板

  • 函数模板调用
    • 函数模板隐式调用
    • 显示调用:函数名<未知类型>(函数参数)
  • 函数模板本质就是函数传参
    • 函数模板也是可以缺省
  • 函数模板中存在变量
    • 这种函数模板必须显示调用
    • 变量传参只能传入常量
  • 当函数模板和普通函数相遇
    • 优先调用类型一致的普通函数
    • 显示调用一定调用模板
  • 函数模板重载
    • 优先调用传参数目少的函数模板
#include<iostream>
#include<string>
using namespace std;
template <class T1> T1 Max(T1 a, T1 b) 
{
	return a > b ? a : b;
}
template <class _T1, class _T2, class _T3> void print(_T1 a, _T2 b, _T3 c) 
{
	cout << a << "\t" << b << "\t" << c << endl;
}
template <class _T1 = int, class _T2 = string, class _T3 = double> void printData(_T1 a, _T2 b, _T3 c)
{
	cout << a << endl << b << endl << c << endl;
}
template <class _T1,int size> _T1* createNew()
{
	_T1* createNew = new _T1[size];
	return createNew;
}
template <class _T1, int size=5> _T1* createParry()
{
	_T1* createNew = new _T1[size];
	return createNew;
}
template <class _Ty, int size = 4> void printArray2(_Ty array[])
{
	for (int i = 0; i < size; i++)
	{
		cout << array[i] << "\t";
	}
	cout << endl;
}
void Func1(int a, double b, string c) 
{
	cout << "普通函数" << endl;
}
template <class _T1, class _T2, class _T3> void Func1(_T1 a,_T2 b,_T3 c) { cout << "三个" << endl; }
template <class _T1, class _T2> void Func1(_T1 a, _T2 b, _T2 c) { cout << "两个" << endl; }
template <class _T1> void Func1(_T1 a,_T1 b,_T1 c) { cout << "一个" << endl; }

void test1() 
{
	//函数模板存在变量,必须显示调用
	int* parry = createNew<int, 5>();
	//变量缺省时候可以隐式调用
	double* king = createParry<double>();
	int p[4] = { 1,2,3,4 };
	printArray2(p);
}
void test2()
{
	//函数模板重载,普通函数
	Func1<int, double, string>(1,1.11,string("king"));
	Func1(1, 1.11,string("king"));
	Func1(1, string("asdd"),string("kkk"));
	Func1(1, 1, 1);
}
int main()
{
	//隐式调用
	cout << Max(1, 2) << endl;
	cout << Max(1.1, 1.2) << endl;
	cout << Max(string("abc"), string("abd")) << endl;
	print(123, string("king"), 1.55);

	//显示调用
	cout << Max<int>(1, 2) << endl;
	cout << Max<string>(string("abc"), string("abd")) << endl;
	print<string, int, double>("asdas", 123, 123.213);

	//函数模板的缺省
	printData(1, "dad", 1.11);
	printData<double, int, string>(1.11, 1, "dasdf");

	test1();
	test2();
	return 0;
}

💓三、函数模板操作自定义类型

操作自定义类型的关键点就是重载

#include<iostream>
#include<string>
using namespace std;
template <class _T1> void printpArry(_T1 arry[],int arryNums)
{
	for (int i = 0; i < arryNums; i++)
	{
		cout << arry[i] << endl;
	}
	cout << endl;
}
template <class _T1> void Sort(_T1 arry[], int arryNums) 
{
	for (int i = 0; i < arryNums; i++)
	{
		for (int j = 0; j < arryNums - i - 1; j++) 
		{
			if (arry[j] > arry[j + 1]) 
			{
				_T1 temp = arry[j];
				arry[j] = arry[j + 1];
				arry[j + 1] = temp;
			}
		}
	}
}
class MM 
{
public:
	MM(string name="", int age=0):name(name),age(age){}
	friend ostream& operator<<(ostream& out,const MM& object)
	{
		out << object.age << "\t" << object.name << endl;
		return out;
	}
	bool operator>(const MM& object) 
	{
		return this->name > object.name;
	}
	string Getname() const { return this->name; }
	int Getage() const { return this->age; }
protected:
	string name;
	int age;
};
template <class _T1> void Sort2(_T1 arry[], int arryNums,bool(*compare)(const _T1& one,const _T1& two))
{
	for (int i = 0; i < arryNums; i++)
	{
		for (int j = 0; j < arryNums - i - 1; j++)
		{
			if (compare(arry[j] , arry[j + 1]))
			{
				_T1 temp = arry[j];
				arry[j] = arry[j + 1];
				arry[j + 1] = temp;
			}
		}
	}
}
bool compareByname(const MM& one, const MM& two)
{
	return one.Getname() > two.Getname();
}
bool compareByage(const MM& one, const MM& two)
{
	return one.Getage() > two.Getage();
}
int main() 
{
	int parry[5] = { 1,20,6,7,90 };
	Sort(parry, 5);
	printpArry(parry, 5);
	MM mm[3];
	mm[0] = { "e",123 };
	mm[1] = { "b",241 };
	mm[2] = { "d",345 };
	Sort(mm, 3);
	printpArry(mm, 3);
	Sort2(mm, 3,compareByage);
	printpArry(mm, 3);
	return 0;
}

💞四、C++类模板

  • template修饰的类就是类模板
  • 模板类必须显示实例化,简单来说必须要传参
  • 模板类不是一个真正的类型
    • 声明和实现必须写在一起,所谓一起就是同一个文件中
    • 所有用到类型的地方必须要用类名<未知类型>的用法
  • 类模板特化
    • 局部特化:特殊化处理,例如两个未知变成一个未知类型
    • 完全特化:具体化类型
#include<iostream>
#include<string>
using namespace std;
template <class _T1,class _T2> class Data
{
public:
	void print();
	static int count;
};
template <class _T1, class _T2> int Data<_T1, _T2>::count = 0;
template <class _T1, class _T2> void Data<_T1, _T2>::print() 
{
	cout << "类中模板函数" << endl;
}
//类模板的继承
template <class _T1, class _T2> class Son : public Data<_T1, _T2> 
{
public:
protected:
};
struct MMinfor 
{
	string name;
	int age;
};
ostream& operator<<(ostream& out, const MMinfor& object) 
{
	out << object.age << "\t" << object.name << endl;
	return out;
}
struct MMscore 
{
	int math;
	int english;
	int chinese;
};
ostream& operator<<(ostream& out, const MMscore& object)
{
	out << object.math << "\t" << object.english << "\t" << object.chinese << endl;
	return out;
}
template <class _T1, class _T2> class MM 
{
public:
	MM(_T1 one,_T2 two):one(one),two(two){}
	void print() { cout << one << "\t" << two << endl; }
protected:
	_T1 one;
	_T2 two;
};
void test1()
{
	MM < string, int > mm("king", 19);
	mm.print();
	MM<int, int> complaxe(1, 1);
	complaxe.print();
	//MMinfor info{string("zhang"), 18};
	//MMscore score{ 13,14,123 };
	//MM<MMinfor, MMscore> king(info, score);
	MM<MMinfor, MMscore> king({ "zhang",18 }, { 31,312,453 });
	king.print();
}
//类模板特化
template <class _T1, class _T2, class _T3> class A
{
public:
	A(_T1 one,_T2 two,_T3 three):one(one),two(two),three(three)
	{
		cout << "三个类型" << endl;
	}
protected:
	_T1 one;
	_T2 two;
	_T3 three;
};
//局部特化
template <class _T1> class A<_T1,_T1,_T1>
{
public:
	A(_T1 one, _T1 two, _T1 three) :one(one), two(two), three(three)
	{
		cout << "局部特化" << endl;
	}
protected:
	_T1 one;
	_T1 two;
	_T1 three;
};
//完全特化
template <> class A<int,int,int>
{
public:
	A(int one, int two, int three) :one(one), two(two), three(three)
	{
		cout << "完全特化" << endl;
	}
protected:
	int one;
	int two;
	int three;
};
void Test() 
{
	A<int, int, int> a(1, 2, 3);
	A<int, string, double> b(1, "as", 1.22);
	A<int, int, double> c(1, 2, 1.22);//三个类型
	A<string, string, string> d("qew", "fasd", "fads");
}
int main()
{
	Data<int, string> data;
	Data<string, int>* object = new Data<string, int>;
	data.print();
	object->print();
	//两个不同类型中的count,不会因为一个类型中值的改变而另一个类型中的值改变
	cout << Data<int, string>::count << endl;
	cout << Data<string, string>::count << endl;
	test1();
	Test();
	return 0;
}

💕五、稍微复杂一点的类模板

稍微复杂一点的模板就是模板类与模板类的嵌套,本质不难,大家学会剥洋葱,学会用别名替换即可

#include<iostream>
#include<string>
using namespace std;
template <class _T1, class _T2> class MM 
{
public:
	MM(_T1 one, _T2 two) :one(one), two(two) {}
	void print() { cout << one << "\t" << two << endl; }
	template <class _T1, class _T2> friend ostream& operator<<(ostream& out,const MM<_T1, _T2>& object);
protected:
	_T1 one;
	_T2 two;
};
template <class _T1, class _T2> ostream& operator<<(ostream& out,const MM<_T1, _T2>& object)
{
	out << object.one << "\t" << object.two << endl;
	return out;
}
template <class _T1, class _T2> class Data 
{
public:
	Data(_T1 one,_T2 two):one(one),two(two){}
	void print() { cout << one << "\t" << two << endl; }
	template <class _T1, class _T2>friend ostream& operator<<(ostream& out, const Data<_T1, _T2>& object);
protected:
	_T1 one;
	_T2 two;
};
template <class _T1, class _T2> ostream& operator<<(ostream& out, const Data<_T1, _T2>& object)
{
	out << object.one << "\t" << object.two << endl;
	return out;
}
int main() 
{
	MM<int, string> info(19, "king");
	MM<int, int> score(99, 88);
	Data< MM<int, string>, MM<int, int>> king(info, score);
	king.print();
	using kk = Data< MM<int, string>, MM<int, int>>;
	using kkk = MM<int, string>;
	Data<kk, kkk> data(king, info);
	data.print();

	return 0;
}

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

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

相关文章

轮廓查找与绘制

轮廓查找与绘制 1)什么是轮廓 轮廓可以简单认为成将连续的点&#xff08;连着边界&#xff09;连在一起的曲线&#xff0c;具有相同的颜色或者灰度&#xff0c;提取轮廓就是提取 这些具有相同颜色或者灰度的曲线&#xff0c;或者说是连通域&#xff0c;轮廓在形状分析和物体…

学习系统编程No.20【进程间通信之命名管道】

引言&#xff1a; 北京时间&#xff1a;2023/4/15/10:34&#xff0c;今天起床时间9:25&#xff0c;睡了快8小时&#xff0c;昨天刷视屏刷了一个小时&#xff0c;本来12点的时候发完博客洗把脸就要睡了&#xff0c;可惜&#xff0c;看到了一个标题&#xff0c;说实话&#xff0…

.Net路由操作!!!!

什么是路由 问题 答案 路由是什么&#xff1f; 路由系统负责处理传入的请求并选择控制器和操作方法来处理它们。 路由系统还用于在视图中生成路由&#xff0c;称为传出的URL 路由有什么用&#xff1f; 路由系统能够灵活地处理请求&#xff0c;面不是将URL与Visual Studio…

MySQL(31)-ubuntu20.04-下安装mysql5.7

ubuntu20.04 下apt 默认安装的是8.0版本&#xff0c;如果要安装5.7版有如下3种方式&#xff1a; 1 下载 MySQL 二进制压缩包&#xff0c;解压并设置相关的参数即可运行 2 通过命令 apt install 进行安装&#xff0c;先下载 MySQL 5.7 对应的源&#xff0c;然后执行安装命令 ap…

5 分钟带你小程序入门 [实战总结分享]

微信小程序常常用 4 种文件类型 JS 文件 JS 在小程序中用于编写页面逻辑和交互效果&#xff0c;可调用 API 接口完成数据请求和处理&#xff0c;也可以使用第三方库和框架。 模块化编程&#xff1a;小程序中JS文件可以使用ES6的模块化语法&#xff0c;通过export和import来…

【vue3】关于watch与computed的用法看这个就ok

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;watch()与computed的使用【vue2中watch|computed概念详解】&#xff0c;本文将介绍在vue3中怎么使用这两者技能 【前言】vue2当中有这两个技能&#xff0c;那么vue3中的watch与compute…

【云原生进阶之容器】第六章容器网络6.4.1--Flannel组网方案综述

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述

【Unity】用HDRI作为Unity的Skybox

教程&#xff1a;用HDRI作为Unity的Skybox 在Unity中&#xff0c;Skybox是用于创建环境背景的一种组件。使用高动态范围图像&#xff08;HDRI&#xff09;作为Skybox可以提供更真实的环境背景。以下是使用HDRI作为Unity Skybox的步骤&#xff1a; 步骤1&#xff1a;下载HDRI图…

进销存管理系统能为企业带来哪些实际效益?

随着互联网的不断发展&#xff0c;如今的商业世界已经越来越向数字化转型。拥有一套完整的数字化的进销存管理能够极大地提升公司货物进出库存情况的效率和准确性&#xff0c;避免过程中出现不必要的错误和漏洞&#xff0c;从而帮助企业更加稳健地自我发展。那么&#xff0c;一…

华为MatePad有什么好用的软件?

现如今伴随着办公方式的转变&#xff0c;人们正迫切地寻找能够顺应时代的“生产力新工具”&#xff0c;它既要能够满足线上/线下灵活切换&#xff0c;又要具备绘画、键入、远程沟通、跨终端联动等多种功能。 对大多数人来说&#xff0c;日常使用华为平板只是满足一下娱乐和生活…

【SSA-LSTM】基于麻雀算法优化LSTM 模型预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

超详细从入门到精通,pytest自动化测试框架实战-fixture固件高级操作(十一)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 参数化fixture fix…

深度学习随笔

一、SPP的作用 解决了训练CNN需要输入图像尺寸一致的问题。 一个CNN可看作由卷积、池化、全连接层组成&#xff0c;由于全连接层的权重矩阵是一个固定值&#xff0c;因此输入全连接层的特征图的维度也必须固定。 SPP利用多尺度思想解决了上述问题&#xff0c;使得神经网络的训练…

2023/4/16总结

深刻的了解了网络编程的一些知识点 socket:套接字 ServerSocket 用来声明服务器 Socket用来声明客户端&#xff0c;其实也不然&#xff0c;在serversocket的accept的方法中&#xff0c;返回的是一个socket变量。我觉得更像一个接口&#xff0c;网络接口。 InternetAddress可以…

PaddlePaddle NLP学习笔记1 词向量

文章目录1.语言模型 Language Model1.1 语言模型是什么1.2 语言模型计算什么1.3 n-gram Language Model2.神经网络语言模型NNLM2.1 N-gram模型的问题3. 词向量3.1 词向量(word Embedding)word2vec 词向量训练算法3.2 如何把词转换为词向量&#xff1f;3.3如何让向量具有语义信息…

Windows 下部署Redis 主从模式+哨兵模式+JAVA连接方式

前言 之前项目需求部署redis高可用&#xff0c;走了很多弯路以及相关配置来回折腾浪费了很多时间&#xff0c;特地记录下。 主从模式&#xff1a;实现多台redis实例进行服务运行&#xff0c;并且数据相互同步&#xff1b; 哨兵模式&#xff1a;实现主服务器和从服务器进行监听…

工业电子中的安森美深力科AMIS30660CANH2RG CAN收发器 面向工业自动化和汽车电源应用

工业电子中的安森美深力科AMIS30660CANH2RG CAN收发器 面向工业自动化和汽车电源应用 AMIS30660CANH2RG CAN 收发器是控制器区域网络 (CAN) 协议控制器和物理总线之间的接口&#xff0c;可在 12 V 和 24 V 系统中使用。该收发器为总线提供差分发射功能&#xff0c;向 CAN 控制…

Spark编程基础-RDD

目录 1.何为RDD 2.RDD的五大特性 3.RDD常用算子 3.1.Transformation算子 1.map() 2.flatMap() 3.reduceByKey() 4 . mapValues() 5. groupBy() 6.filter() 7.distinct() 8.union() 9.join() 10.intersection() 11.glom() 12.gruopBykey() 13.sortBy() 14.sortByKey …

docker+docker-compose+nginx前后端分离项目部署

文章目录1.安装docker1.1 基于centos的安装1.2 基于ubuntu2.配置国内加速器2.1 配置阿里云加速器&#x1f340; 找到相应页面&#x1f340; 创建 docker 目录&#x1f340; 创建 daemon.json 文件&#x1f340; 重新加载服务配置文件&#x1f340; 重启 docker 引擎2.2 配置网易…

OJ系统刷题 第八篇

13415 - 津津的储蓄计划 时间限制 : 1 秒 内存限制 : 128 MB 津津的零花钱一直都是自己管理。每个月的月初妈妈给津津300元钱&#xff0c;津津会预算这个月的花销&#xff0c;并且总能做到实际花销和预算的相同。 为了让津津学习如何储蓄&#xff0c;妈妈提出&#xff0c;津…