一文带你掌握C++模版

news2024/11/23 17:07:20

12. C++模板

什么是模板

模板编程也可以叫做泛型编程,忽略数据类型的一种编程方式

//求最值问题
int  Max(int a,int b)
{
	return a>b?a:b;    
}
double Max(int a,int b)
{
	return a>b?a:b;        
}
string Max(string a,string b)
{
	return a>b?a:b;        
}
//引入模板编程
template <typename  type>   //告诉编译器,下面会用到一个未知类型叫做type
type Max(type a,type b)
{
	return a>b?a:b;        
}

模板代码

#include <iostream>
using namespace std;
template <typename type> 
type Max(type a, type b) 
{
	return a > b ? a : b;
}
//typename 可以用class 替换
template <class T>
void print(T data) 
{
	cout << data << endl;
}

int main() 
{
	//隐式调用
	cout << Max(1, 2) << endl;
	cout << Max(1.1, 2.2) << endl;
	//string 和char* 有区别
	cout << Max(string("1ILoveyou"), string("2IMissyou")) << endl;
	//显示调用 <>传类型的参数
	cout << Max<int>(1, 2) << endl;		//type=int  a=1 b=2
	cout << Max<string>(string("1"), string("2")) << endl;
	cout << Max<double>(1.2, 1.3) << endl;
	return 0;
}

函数模板

函数模板重载问题

  • 函数模板和普通函数

  • 函数模板和函数模板

#include <iostream>
using namespace std;
//No.1 模板与普通函数
int Max(int a, int b) 
{
	cout << "普通函数..." << endl;
	return a > b ? a : b;
}
template <class T>
T Max(T a, T b) 
{
	cout << "模板" << endl;
	return a > b ? a : b;
}
//No.2 模板与模板
template <class type1,class type2,class type3>
void print(type1 one, type2 two, type3 three) 
{
	cout << "三只" << endl;
}

template <class type1,class type2>				//type1=int type2=double
void print(type1 one, type1 two, type2 tow)     //int int double
{
	cout << "两只" << endl;
}
template <class type>
void print(type one, type two, type three) 
{
	cout << "一只" << endl;
}


int main() 
{
	cout << Max<int>(1, 2) << endl;		//显式调用,百分百调用模板
	cout << Max(1, 2) << endl;			//优先调用类型确定的函数
	cout << "显示调用" << endl;
	print<int, double, string>(1, 1.1, string("23"));
	print<int, double>(1, 1, 1.22);
	print<int>(1, 2, 3);
	cout << "隐式调用" << endl;
	print(1, 1, 2);						//需要传参越少先调用
	print(1, 1, string("sdsd"));		
	print(1, 1.11, string("sdsd"));		//只有一种选择
	return 0;
}

类成员函数是函数模板

//这种不叫做模板类型
class  MM 
{
public:
	template <class T>
	void print(T data) 
	{
		cout << data << endl;
	}
protected:

};
int main()
{
    MM mm;
	mm.print(1);
	mm.print<string>("string");
	return 0;    
}

函数模板缺省

函数模板缺省和函数参数的缺省是一样的规则

//函数模板缺省
template <class type1,class type2=string>
void printData(type1 one, type2 two) 
{
	cout << one << endl;
	cout << two << endl;
}
int main()
{

    printData<int, double>(1, 1.22);
	printData<int>(1, string("dsfsdf"));
    return 0;
}

函数模板传常量

//函数模板传常量
template <class T,size_t size>
void printArray(T* array) 
{
	for (int i = 0; i < size; i++) 
	{
		cout << array[i] << " ";
	}
	cout << endl;
}
int main()
{
	int num[3] = { 1,2,3 };
	printArray<int, 3>(num);
	//下面代码报错
	//int length = 3;
	//printArray<int, length>(num);
	string str[4] = { "sdds","sd","sdsd" ,"sdds"};
	printArray<string, 4>(str);
    return 0;
}

类模板

类模板的基础

  • 怎么写类模板

  • 类模板不是一个完整类型,所以任何用到类名的地方都需要用类名<未知类型>的方式使用

  • 怎么去使用类模板,类模板必须采用显式调用方式

  • 类模板在多文件中不能分开写

  • 可以写在.hpp文件中(声明和实现都在一起)

#include <iostream>
#include <map>
using namespace std;
template <class type1,class type2>
struct my_pair 
{
	type1 first;		//键
	type2 second;		//值
	my_pair(type1 first, type2 second) :first(first), second(second) {}
	my_pair() = default;
};
template <class type1,class type2>
my_pair<type1, type2> my_make_pair(type1 one, type2 two) 
{
	return my_pair<type1, type2>(one, two);
}

template <class type1,class type2>
class Test 
{
public:
	Test(type1 one, type2 two) :one(one), two(two) 
	{

	}
	void printTest();
protected:
	type1 one;
	type2 two;
};
template <class type1, class type2>
void Test<type1,type2>::printTest() 
{
	cout << one << " " << two << endl;
}

template <class type1,class type2>
class Data :public Test<type1,type2> 
{
public:
	Data(type1 one, type2 two) :Test<type1, type2>(one, two) 
	{

	}
protected:
};


int main() 
{
	my_pair<int,int> pairData = { 1,2 };
	cout << pairData.first << " " << pairData.second << endl;
	my_pair<int, string>* p = new my_pair<int, string>;
	p->first = 12;
	p->second = "sdsd";
	cout << p->first << " " << p->second << endl;
	
	Data<int, int>  data(1, 2);
	data.printTest();

	//标准库中的pair类型
	pair<int, string> pD(1, "ILoveyou");
	cout << pD.first << " " << pD.second << endl;

	pair<int, string> testData = make_pair<int, string>(1, "sdfsdf");
	my_pair<int, string> my_testData =my_make_pair<int, string>(1, "sdfsdf");

	return 0;
}

类模板特化问题

  • 局部特化
  • 完全特化

特化的目的是为了适应不同数据的不同处理

#include <iostream>
using namespace std;
template <class _Ty1,class _Ty2,class _Ty3>
class Data
{
public:
	Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) {}
	void printData()
	{
		cout << (one + two + three) << endl;
	}
private:
	_Ty1 one;
	_Ty2 two;
	_Ty3 three;
};

//局部特化
//两个数据,打印两数之差
template <class _Ty1,class _Ty2>
class Data<_Ty1,_Ty1,_Ty2> 
{
public:
	Data(_Ty1 one, _Ty2 two) :one(one), two(two){}
	void printData()
	{
		cout << (one -two) << endl;
	}
private:
	_Ty1 one;
	_Ty2 two;
};
//只有一个数据,打印数据
template <class _Ty1>
class Data<_Ty1,_Ty1,_Ty1>
{
public:
	Data(_Ty1 one) :one(one){}
	void printData()
	{
		cout << one << endl;
	}
private:
	_Ty1 one;
};

//完全特化
template <>
class Data<string, string, string> 
{
public:
	Data(string one,string two,string three):one(one),two(two),three(three)
	{

	}
	void printData();
private:
	string one;
	string two;
	string three;
};
void Data<string,string,string>::printData()
{
	cout << one << " " << two << " " << three << endl;
}

int main() 
{

	Data<int, int, int> data1(1);
	data1.printData();
	Data<int,int, double> data2(2, 1);
	data2.printData();
	Data<int, double, float> data3(1, 1.1, 1.2f);
	data3.printData();
	Data<string, string, string> data4("dsd","sdfd","sdfdsf");
	data4.printData();
	return 0;
}

模板操作自定义类型

模板操作自定义关键点在于重载

#include <iostream>
#include <algorithm>
using namespace std;


class MM 
{
public:
	MM() = default;
	MM(string name, int age) :name(name), age(age) {}
	friend ostream& operator<<(ostream& out, const MM& object) 
	{
		out << object.name << " " << object.age;
		return out;
	}
private:
	string name;
	int age;
};

template <class _Ty>
void printData(_Ty data)
{
	cout << data << endl;
}

template <class _Ty1,class _Ty2,class _Ty3>
class Data
{
public:
	//_Ty1=MM, _Ty2=int, _Ty3=int
	Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three)
	{

	}
	void printData() 
	{
		cout << one << " " << two << " " << three << endl;
	}
private:
	_Ty1 one;
	_Ty2 two;
	_Ty3 three;
};

int main()
{
	printData(1);
	printData("string");
	MM mm = { "小芳",18 };
	printData(mm);

	Data<MM, int, int> data(MM("小芳",18),98,99);
	data.printData();

	Data<MM, MM, MM> mmData(MM("小芳", 18), MM("小芳", 18), MM("小芳", 18));
	mmData.printData();
	return 0;
}

模板嵌套模板

  • 关键点在于大家自己要清楚类型如何表示(类型是由类名<类型>表示一个类型)
#include <iostream>
using namespace std;
template <class _Ty1,class _Ty2,class _Ty3>
class Data 
{
public:
	Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) {}
	void printData() 
	{
		cout << one << " " << two << " " << three << endl;
	}
	friend ostream& operator<<(ostream& out, Data<_Ty1, _Ty2, _Ty3>& object)
	{
		out << object.one << " " << object.two << " " << object.three;
		return out;
	}
protected:
	_Ty1 one;
	_Ty2 two;
	_Ty3 three;
};

template <class _Ty1, class _Ty2>
class Info
{
public:
	Info(_Ty1 one, _Ty2 two) :one(one), two(two) {}
	void printData()
	{
		cout << one << " " << two << endl;
	}
	//template <class _Ty1, class _Ty2>  类中实现不需要修饰了,会出现重定义问题
	friend ostream& operator<<(ostream& out, Info<_Ty1, _Ty2>& object)
	{
		out << object.one << " " << object.two << " ";
		return out;
	}
protected:
	_Ty1 one;
	_Ty2 two;

};
template <class _Ty1>
class Student
{
public:
	Student(_Ty1 one) :one(one) {}
	void printData() 
	{
		cout << one << endl;
	}
protected:
	_Ty1 one;
};


int main() 
{
	Data<int, int, int> data(1,1,1);  //Data<int, int, int>
	Info<int, int> info(1, 2);		  //Info<int, int>
	
	Info<Data<int, int, int>, Data<string, string, string>>
		test1(Data<int, int, int>(1, 1, 1), Data<string, string, string>("ds", "sd", "sds"));
	//起别名
	using type1 = Data<int, int, int>;
	using type2 = Data<string, string, string>;
	//别名版本
	Info<type1, type2>test2(type1(1, 1, 1), type2("ds", "sd", "sds"));

	Data<Info<int, string>, Info<string, string>, Info<int, double>> 
		test3(Info<int, string>(1,"sd"), Info<string, string>("sdds","dsds"),Info<int, double>(1,1.11));

	test1.printData();
	test2.printData();
	test3.printData();

	Student<Data<Info<int, int>, Info<int, string>, Info<string, string>>> 
		stu(Data<Info<int, int>, Info<int, string>, Info<string, string>>
			(Info<int, int>(1,1), Info<int, string>(1,"sdsd"), Info<string, string>("sds","sdsd")));

	stu.printData();
	return 0;
}

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

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

相关文章

搭建Nginx正向代理服务器,轻松实现外部网络请求的转发

​ 本文将介绍如何使用Nginx搭建一个简单的正向代理服务器&#xff0c;实现外部网络请求的转发。通过设置正向代理&#xff0c;我们可以隐藏真实的服务器地址&#xff0c;提高访问速度&#xff0c;以及增强网络安全性 一、Nginx正向代理简介 正向代理&#xff08;Forward Pro…

基于node的学生公寓管理系统-计算机毕设 附源码 06412

基于node的学生公寓管理系统 摘 要 本论文主要论述了如何使用Node.js框架和Express框架开发一个基于Node的学生公寓管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S结构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0…

无人机环保行业解决方案-应急环境污染处理

无人机环境应急处理 传统环境应急的典型挑战 发生环境应急事件时&#xff0c;最重要的是快速获取前方信息。然而&#xff0c;有毒气体 和易燃易爆品多&#xff0c;存在二次爆炸风险&#xff0c;严重威胁人身安全。无人机可快 速赶到事故现场&#xff0c;查看周边环境、污染物…

免费开源的搜索工具,支持搜索文件内容,绿色免安装

dnGrep是一款功能强大的开源Windows搜索工具&#xff0c;旨在帮助用户高效地在各种文档和压缩文件中查找文本内容。它支持多种查询方式&#xff0c;包括文本、正则表达式&#xff08;Regex&#xff09;、XPath以及音序查询。 dnGrep主要功能&#xff1a; 多格式支持&#xff…

网络安全学习平台top10_网络安全训练平台

前言 1.Hack In The Box&#xff1a;http://www.hackinthebox.org/ 2.Hellbound Hackers&#xff1a;https://www.hellboundhackers.org/ 3.Exploit Database&#xff1a;https://www.exploit-database.net/ 4.Hacking-Tutorial&#xff1a;https://www.hacking-tutorial.c…

【Python实战】如何优雅地实现 PDF 去水印?

话接上篇&#xff0c;自动化处理 PDF 文档&#xff0c;完美实现 WPS 会员功能 小伙伴们更关心的是如何去除 PDF 中的水印~ 今天&#xff0c;就来分享一个超简单的 PDF 去水印方法~ 1. 原理介绍 在上一篇中&#xff0c;我们介绍了如何将 PDF 文档转换成图片&#xff0c;图片…

前端必知必会-html中input的type设置

文章目录 HTML type的设置输入类型文本输入类型密码输入类型提交输入类型重置输入类型单选按钮输入类型复选框输入类型按钮输入类型颜色输入类型日期输入类型 Datetime-local输入类型电子邮件输入类型图像输入类型 文件输入类型 隐藏输入类型 月份输入类型 数字输入类型范围输入…

更换收银系统时如何迁移会员数据

系统介绍 专门为零售行业的连锁店量身打造的收银系统&#xff0c;适用于常规超市、生鲜超市、水果店、便利店、零食专卖店、服装店、母婴用品、农贸市场等类型的门店使用。同时线上线下数据打通&#xff0c;线下收银的数据与小程序私域商城中的数据完全同步&#xff0c;如商品…

js 实现数组转树形数据(2024-08-01)

要将数组转换为树形结构&#xff0c;通常需要一个数组&#xff0c;其中每个元素都包含一个父节点的引用。以下是一个使用JavaScript实现的函数&#xff0c;假设每个元素都有一个唯一的 【id 】和一个指向其父元素的【pId】 /*** 数组转树形结构* param {array} list 被转换的数…

【编程刷级之路】大学新生的最佳入门攻略

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《热点时事》 期待您的关注 目录 引言 方向一&#xff1a;编程语言选择 方向二&#xff1a;学习资源推荐 方向三&#xff1a;学…

django体育器材后台管理系统-毕业设计源码45411

django体育器材后台管理系统 摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学…

对抗搜索Adversary Search与Minmax算法(含python代码)

Adversary Search&#xff0c;也称为对抗搜索&#xff0c;是人工智能中的一种算法策略&#xff0c;主要用于解决那些需要两个或多个对手在完全或部分信息的环境下对抗的问题。这种类型的搜索算法广泛应用于各种策略游戏&#xff0c;如国际象棋、围棋、和井字游戏&#xff0c;其…

张宇1000题/660/880/武忠祥严选题,哪本优先级高?最接近真题?

使用资料&#xff1a; 武老师强化班视频高数辅导讲义严选题 具体操作&#xff1a; 预习讲义10页听课做严选题 情况一&#xff1a;基础阶段跟着武老师并且完成660的同学。 这些同学在强化阶段可以在使用上述资料的基础上&#xff0c;再加一本李林老师的880题。可能有同学不…

论文解读(14)-GeoCLIP

加油&#xff0c;加油&#xff01; 原文&#xff1a; GeoCLIP: Clip-Inspired Alignment between Locations and Images for Effective Worldwide Geo-localization &#xff08;2309.16020 (arxiv.org)&#xff09; 这一篇的重点在于范围放宽到全球了 摘要 首先指出了目前…

opencascade AIS_Triangulation源码学习 每个三角形顶点关联颜色

opencascade AIS_Triangulation 每个三角形顶点关联颜色 前言 交互对象&#xff0c;从 Poly_Triangulation 绘制数据&#xff0c;可选择性地带有与每个三角形顶点关联的颜色。 为了最大效率&#xff0c;颜色以32位整数表示&#xff0c;而不是传统的 Quantity_Color 值。 目前尚…

Swift中@escaping的理解与使用

当我们在一个方法中将一个闭包当做参数的时候&#xff0c;那么就有很大概率用到这个escaping关键字了&#xff0c;试想一般什么时候会将闭包当做参数传进来呢&#xff1f;很多时候比如方法里面有异步操作&#xff0c;需要方法先return&#xff0c;最后再调用闭包返回结果&#…

论数据驱动的优雅:构建轻量高效的数据中台-亿发

随着数据处理需求的不断增长&#xff0c;各类企业都在探索如何更高效地管理和利用数据。特别是在大规模数据应用的背景下&#xff0c;数据中台成为了众多企业优化数据管理的关键解决方案。从数据中台的建设需求到其实际应用&#xff0c;本文将详细解析数据中台的发展历程、建设…

.NET 一款反序列化打入冰蝎内存马的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

用Python编写你的网络监控系统详解

概要 在现代网络管理中,实时监控网络流量和状态是保证网络正常运行的关键。使用Python编写网络监控工具可以帮助管理员及时发现和解决网络问题。本文将详细介绍如何使用Python编写网络监控工具,包括基本概念、常用库及其应用场景,并提供相应的示例代码。 网络监控的基本概念…

nginx反向代理严重错误[crit] (13: Permission denied) while reading upstream问题

nginx作为使用最广泛的一款反向代理软件&#xff0c;其性能也是非常优秀的&#xff0c;一般情况下&#xff0c;直接配置就可以使用&#xff0c;而且也都是稳定高效的&#xff0c;但是在实际应用中&#xff0c;对于不同的应用场景&#xff0c;总是会出现各种各样的问题&#xff…