【C++】了解模板

这里是目录

  • 前言
  • 函数模板
  • 函数模板的实例化
  • 类模板

前言

如果我们要交换两个数字,那么我们就需要写一个Swap函数来进行交换,那如果我们要交换char类型的数据呢?那又要写一份Swap的函数重载,参数的两个类型是char,那我们还要交换double类型的数据呢?难道又要写一份Swap函数重载?如果在添加个自定义类型的交换呢?
模板的作用就是解决此类问题,模板的主要功能是实现通用

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}

void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
}

void Swap(char& left, char& right)
{
	char temp = left;
	left = right;
	right = temp;
}

函数模板

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本

基本用法:

template<typename T>
//这里的typename也可以换为class,一般情况下用typename居多
//也可以多参数
template<class T1, class T2>

实现一个交换函数模板:

template<typename T>
void Swap(T& x, T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

template<typename T> //模板参数 一般命名为T TY TP
void Swap(T& x, T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

int main()
{
	int a = 2, b = 1;
	double c = 2.2, d = 1.1;
	cout << "交换前->" << a << " " << b << endl;
	Swap(a, b);
	cout << "交换后->" << a << " " << b << endl;

	cout << "交换前->" << c << " " << d << endl;
	Swap(c, d);
	cout << "交换后->" << c << " " << d << endl;

	return 0;
}

运行效果:
在这里插入图片描述
可以看到已经完成了交换,但实际上他们调用的并不是同一个函数,在编译器上看他们确实是调用的同一个函数,但是如果查看汇编就能发现他们调用的是不同的函数

在这里插入图片描述

可以看到调用的函数地址不相同

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

模板的实例化图解:
在这里插入图片描述
C++库中是有交换函数的,只不过库里的是小写,所以我们以后想要交换数据直接用库里的就好了
在这里插入图片描述
函数模板可以有多个参数

template<typename T1,typename T2>
void Func(const T1& x, const T2& y)
{
	cout << x << " " << y << endl;
}

函数模板可以做返回值

template<typename T1,typename T2>
T1 Func(const T1& x, const T2& y)
{
	cout << x << " " << y << endl;

	return x;
}

函数模板实例化生成具体函数
函数模板根据调用,自己推导模板参数的类型,实例化出对应的函数

函数模板的实例化

模板的实例化有两种方式
一种是隐式实例化:让编译器根据实参推演模板参数的实际类型
还有一种是显式实例化:在函数名后的<>中指定模板参数的实际类型

template<typename T>
T Add(const T& left, const T& right)
{
	return left + right;
}

int main()
{
	int a = 10;
	int b = 20;
	double c = 10.0;
	double d = 20.0;
	//编译器自动推导
	cout << Add(a, b) << endl;
	cout << Add(c, d) << endl;
	//但是下面这种场景如果让编译器自动推导就会出问题
	cout << Add(a, d) << endl;

	return 0;
}

左边的T是int右边的T是double,那到底是T推导成int还是double呢?
这时候编译器就会出现问题了

错误信息:
在这里插入图片描述
有两种方法可以解决这个问题
方法一:

cout << Add(a, (int)d) << endl;
cout << Add((double)a, d) << endl;

这样就不会出现推导歧义了

方法二:

//显式实例化,用指定类型实例化
cout << Add<int>(a, d) << endl;
cout << Add<double>(a, d) << endl;

大部分模板都不需要显式实例化,只有少数需要
比如:

template<typename T>
T* Alloc(int n)
{
	return new T[n];
}

int main()
{
	//有些函数无法自动推导,只能显式实例化
	double* arr = Alloc<double>(10);

	return 0;
}

类模板

//类模板
template<typename T>
class Stack
{
public:
	Stack(size_t capacity = 3)
	{
		_array = new T[capacity];
		_capacity = capacity;
		_size = 0;
	}
	
private:
	T* _array;
	int _capacity;
	int _size;
};

int main()
{
	Stack<int> s1;
	Stack<double> s2;
	Stack<char> s3;

	return 0;
}

有了类模板就可以实现一个栈存储多类型的需求

类模板的声明和定义分离和普通的类不同:

//类模板
template<typename T>
class Stack
{
public:
	Stack(size_t capacity = 3);

private:
	T* _array;
	int _capacity;
	int _size;
};

//普通类,类名和类型是一样的
//类模板,类名和类型不一样,
//类名是:Stack
//类型是:Stack<T>
//最好不要分离到两个文件
template<typename T>
Stack<T>::Stack(size_t capacity)
{
	_array = new T[capacity];
	_capacity = capacity;
	_size = 0;
}

int main()
{
	//类模板实例化
	Stack<int> s1;
	Stack<double> s2;
	Stack<char> s3;

	return 0;
}

总结:

优点:

  1. 灵活性, 可重用性和可扩展性
  2. 可以大大减少开发时间,模板可以把用同一个算法去适用于不同类型数据,在编译时确定具体的数据类型
  3. 模版模拟多态要比C++类继承实现多态效率要高,无虚函数,无继承

缺点:

  1. 可读性不好,调试比较困难
  2. 模板的数据类型只能在编译时才能被确定
  3. 所有用基于模板算法的实现必须包含在整个设计的.h头文件中, 当工程比较大的时候, 编译时间较长

以上就是本篇文章的全部内容了,希望大家看完能有所收获

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Rocketmq架构

NameServer&#xff1a;作为注册中心&#xff0c;提供路由注册、路由踢出、路由发现功能&#xff0c;舍弃强一致&#xff0c;保证高可用&#xff0c;集群中各个节点不会实时通讯&#xff0c;其中一个节点下线之后&#xff0c;会提供另外一个节点保证路由功能。 Rocket mq name…

AI视觉识别有哪些工业应用

AI视觉识别&#xff0c;主要是利用人工智能算法对图像或视频数据进行分析和处理&#xff0c;以提取关键信息并执行筛选、判断、预警等任务。AI视觉识别涵盖多种应用&#xff0c;如人脸识别、目标检测和识别、图像分割、行为识别、视频分析等。本篇就简单介绍一下AI视觉识别的应…

传智杯第五届题解

B.莲子的机械动力学 分析&#xff1a;这题有个小坑&#xff0c;如果是00 0&#xff0c;结果记得要输出0。 得到的教训是&#xff0c;避免前导0出现时&#xff0c;要注意答案为0的情况。否则有可能会没有输出 #include<assert.h> #include<cstdio> #include<…

J签证、移民、绿卡都是怎么回事?

随着全球化的不断推进&#xff0c;越来越多的人开始关注国际间的移民与签证政策&#xff0c;其中包括J签证、移民以及绿卡的申请问题。本文将简要介绍J签证、移民绿卡的基本概念&#xff0c;并提供相关申请的一般步骤&#xff0c;以帮助读者更好地了解这些程序。 首先&#xff…

【raect.js + hooks】useRef 搭配 Houdini 创造 useRipple

水波纹点击特效 really cool&#xff0c;实现水波纹的方案也有很多&#xff0c;笔者经常使用 material 组件&#xff0c;非常喜欢 mui 中的 ripple&#xff0c;他家的 ripple 特效就是通过 css Houdini 实现的。 今天&#xff0c;我们将复刻一个 ripple&#xff0c;并封装成 ho…

vue3 router-view 使用keep-alive报错parentcomponent.ctx.deactivate is not a function

问题 如下图&#xff0c;在component组件上添加v-if判断&#xff0c;会报错: parentcomponent.ctx.deactivate is not a function 解决方法 去除v-if&#xff0c;将key直接添加上。由于有的公用页面&#xff0c;需要刷新&#xff0c;不希望缓存&#xff0c;所以需要添加key…

【23真题】快跑,考太偏了这所211!

今天分享的是23年湖南师范997的信号与系统试题及解析。 小马哥Tips&#xff1a; 本套试卷难度分析&#xff1a;22年湖南师范997考研真题&#xff0c;我也发布过&#xff0c;若有需要&#xff0c;戳这里自取&#xff01;本套试题难度中等&#xff0c;题量适中&#xff0c;但是…

升级python后sudo apt-get update报错

sudo apt-get update 报错&#xff1a; sh: /usr/lib/cnf-update-db: /usr/bin/python3.7.5: bad interpreter: No such file or directory Reading package lists... Done E: Problem executing scripts APT::Update::Post-Invoke-Success if /usr/bin/test -w /var/lib/c…

CANDENCE: PCB 如何高亮网络、器件

PCB 如何高亮网络、器件 开始前先学习一个单词&#xff1a;assign CANDECE 高亮网络 step1: 选择一个颜色&#xff1a;红色 step2: 筛选要高亮什么&#xff1a;网络 or 器件&#xff0c;这里选择网络。 step3&#xff1a;鼠标点击要高亮的网络&#xff1a; 这里是GND 这里…

罐装葡萄酒会成为主流吗?

许多人认为罐装葡萄酒可能是葡萄酒行业的下一个大事件&#xff0c;一个有待提出的问题&#xff0c;罐装葡萄酒会成为主流吗&#xff1f;来自云仓酒庄品牌雷盛红酒分享还是这种形式的基础永远会限制它的吸引力&#xff1f;在这里&#xff0c;我们一起来探讨支持和反对罐装葡萄酒…

力扣题:单词-11.20

力扣题-11.20 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;58. 最后一个单词的长度 解题思想&#xff1a;按空格划分&#xff0c;然后统计单词长度即可 class Solution(object):def lengthOfLastWord(self, s):""":type s: str…

Java——TreeSet用法

Java——TreeSet TreeSet 是 Java 中的一个有序集合类&#xff0c;它基于红黑树&#xff08;Red-Black Tree&#xff09;实现。 下面详细介绍 TreeSet 的用法和特点&#xff1a; 有序性&#xff1a;TreeSet 中的元素按照自然顺序或者通过自定义的比较器进行排序。它保证了元素…

网工内推 | 云计算运维,云相关认证优先,最高30K,带薪年假

01 安畅网络 招聘岗位&#xff1a;云计算运维工程师 职责描述&#xff1a; 1、负责对公有云平台的计算、存储、网络资源等IAAS/SAAS/PAAS层产品组件日常交付部署运维工作&#xff0c;包括调试、配置、维护、监控、优化等工作&#xff1b; 2、负责对操作系统及应用日常运行维护…

OSG编程指南<十七>:OSG光照与材质

1、OSG光照 OSG 全面支持 OpenGL 的光照特性&#xff0c;包括材质属性&#xff08;material property&#xff09;、光照属性&#xff08;light property&#xff09;和光照模型&#xff08;lighting model&#xff09;。与 OpenGL 相似&#xff0c;OSG 中的光源也是不可见的&a…

java拦截器,过滤器,监听器的区别

拦截器与过滤器 1&#xff1a;过滤器 过滤器主要作用在请求到达Servlet之前&#xff0c;对请求进行预处理&#xff0c;可以对HTTP请求进行过滤、修改。过滤器通常用于日志记录、字符编码转换、权限检查等任务。过滤器是基于回调函数实现的&#xff0c;重写doFilter()方法实现过…

AT89S52单片机智能寻迹小车自动红外避障趋光检测发声发光设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;寻迹 获取完整说明报告源程序数据 小车具有以下几个功能&#xff1a;自动避障功能&#xff1b;寻迹功能&#xff08;按路面的黑色轨道行驶&#xff09;&#xff1b;趋光功能&#xff08;寻找前方的点光源并行驶到位&…

MatchPyramid实现文本匹配

引言 今天利用MatchPyramid实现文本匹配。 原论文解析→点此←。 MatchPyramid 核心思想是计算两段文本间的匹配矩阵&#xff0c;把它当成一个图形利用多层卷积网络提取不同层级的交互模式。 匹配矩阵是通过计算两段输入文本基本单元(比如字或词)之间相似度得到的&#xf…

windows系统bat脚本命令总结之EnableDelayedExpansion

前言 做了一段时间的bat脚本开发&#xff0c;bat脚本中有各种各样的命令跟传统的编程逻辑完全不同&#xff0c;本专栏会讲解下各种各式的命令使用方法。 本篇文章讲解的是EnableDelayedExpansion的使用。 EnableDelayedExpansion简介 EnableDelayedExpansion是用于在批处理脚本…

Linux:理解文件重定向

文章目录 文件内核对象fd的分配问题重定向的现象dup2 重定向的使用标准输出和标准错误 前面对于文件有了基本的认知&#xff0c;那么基于前面的认知&#xff0c;本篇总结的是文件重定向的含义极其本质 文件内核对象 首先理解一下file内核对象是什么&#xff0c;回顾一下下面这…

python-nmap库使用教程(Nmap网络扫描器的Python接口)(功能:主机发现、端口扫描、操作系统识别等)

文章目录 Python-nmap库使用教程前置条件引入python-nmap创建Nmap扫描实例执行简单的主机发现&#xff08;nmap -sn&#xff09;示例&#xff0c;我有一台主机配置为不响应 ICMP 请求&#xff0c;但使用nmap -sn&#xff0c;仍然能够探测到设备&#xff1a; 端口扫描扫描特定端…