【C++】了解模板

news2024/9/22 17:28:33

这里是目录

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

前言

如果我们要交换两个数字,那么我们就需要写一个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.coloradmin.cn/o/1272952.html

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

相关文章

【排序,直接插入排序 折半插入排序 希尔插入排序】

文章目录 排序排序方法的分类插入排序直接插入排序折半插入排序希尔插入排序 排序 将一组杂乱无章的数据按照一定规律排列起来。将无序序列排成一个有序序列。 排序方法的分类 储存介质&#xff1a; 内部排序&#xff1a;数据量不大&#xff0c;数据在内存&#xff0c;无需…

【FPGA图像处理】——DDR仲裁、多输入源拼接、旋转任意角度、突发长度修改、任意地址读取。

前言&#xff1a;做FPGA大赛期间遇到的问题&#xff0c;自己coding过程。 包含&#xff1a;hdmi、摄像头等多输入源的拼接&#xff1b;了解DDR以及多种DMA传输方式&#xff0c;修改底层突发长度以及存储位宽&#xff1b;单输入源任意角度旋转&#xff08;无需降低帧率&#xff…

tex2D使用学习

1. 背景&#xff1a; 项目中使用到了纹理进行插值的加速&#xff0c;因此记录一些自己在学习tex2D的一些过程 2. 代码&#xff1a; #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <assert.h> #include <stdio.h>…

XTU OJ 1339 Interprime 学习笔记

链接 传送门 代码 #include<bits/stdc.h> using namespace std;const int N1e610; //78498 我计算了一下&#xff0c;6个0的范围内有这么多个素数&#xff0c;所以开这么大的数组存素数 //计算的代码是一个循环 int prime[80000]; int a[N],s[N];//s数组是前缀和数组b…

自定义链 SNAT / DNAT 实验举例

参考原理图 实验前的环境搭建 1. 准备三台虚拟机&#xff0c;定义为内网&#xff0c;外网以及网卡服务器 2. 给网卡服务器添加网卡 3. 将三台虚拟机的防火墙和安全终端全部关掉 systemctl stop firewalld && setenforce 0 4. 给内网虚拟机和外网虚拟机 yum安装 httpd…

Echarts的引入使用

ECharts文档 1.下载并引入Echarts 2.准备一个具备大小的DOM容器 3.初始化echarts实例对象 4.指定配置项和数据(option) 5.将配置项设置给echarts实例对象 最后是一个js文件 echarts的引入 1.引入echarts - js 文件 <script src"js/echarts.min.js"></scri…

「Linux」使用C语言制作简易Shell

&#x1f4bb;文章目录 &#x1f4c4;前言简易shell实现shell的概念系统环境变量shell的结构定义内建命令完整代码 &#x1f4d3;总结 &#x1f4c4;前言 对于很多学习后端的同学来讲&#xff0c;学习了C语言&#xff0c;发现除了能写出那个经典的“hello world”以外&#xff…

XUbuntu22.04之OBS30.0设置录制音频降噪(一百九十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

LabVIEWL实现鸟巢等大型结构健康监测

LabVIEWL实现鸟巢等大型结构健康监测 管理国家地震防备和减灾的政府机构中国地震局(CEA)选择了七座新建的巨型结构作为结构健康监测(SHM)技术的测试台。这些标志性建筑包括北京2008年夏季奥运会场馆&#xff08;包括北京国家体育场和北京国家游泳中心&#xff09;、上海104层的…

QML学习一、GridView的使用和增加添加动画、删除动画

一、效果预览 二、源码分享 import QtQuick import QtQuick.ControlsApplicationWindow {visible: truewidth: 640height: 480title: "Test"property int cnt:cnt model.countListModel{id:modelListElement{index:0}ListElement{index:1}ListElement{index:2}List…

csapp-linklab之第3阶段“输出学号”实验报告(强弱符号)

题目 新建一个phase3_patch.o&#xff0c;使其与main.o和phase3.o链接后&#xff0c;运行输出自己的学号&#xff1a; $ gcc -o linkbomb main.o phase3.o phase3_patch.o $ ./linkbomb $学号 提示 利用符号解析中的强弱符号规则。&#xff08;COOKIE字符串未初始化&#xff…

单片机AVR单片机病房控制系统设计+源程序

一、系统方案 设计一个可容8张床位的病房呼叫系统。要求每个床位都有一个按钮&#xff0c;当患者需要呼叫护士时&#xff0c;按下按钮&#xff0c;此时护士值班室内的呼叫系统板上显示该患者的床位号&#xff0c;并蜂鸣器报警。当护士按下“响应”键时&#xff0c;结束当前呼叫…

【无标题】读transformer

这里写目录标题 transformerabstractconclusionintroductionbackground注意力机制mlptransformer和RNN传递序列信息embedding之后维度越大的向量归一化后其单个值就越小&#xff0c;乘个根号512position encoding加入时序信息 transformer abstract 编码器和解码器的架构 处理…

强化学习中的Q学习

Q学习&#xff08;Q-Learning&#xff09;是强化学习中的一种基于值的学习方法&#xff0c;用于在有限马尔可夫决策过程&#xff08;MDP&#xff09;中学习最优的动作策略。Q学习主要用于离散状态和离散动作的问题。 以下是Q学习的基本概念和步骤&#xff1a; Q-Value&#xf…

程序员也需要养生——程序员睡不好,重视一下你的情绪吧

程序员也需要养生——程序员睡不好&#xff0c;重视一下你的情绪吧 睡眠是一个复杂的系统工程&#xff0c;可以促进生长发育&#xff0c;修复受损的组织。促进大脑细胞的修复等等。在情绪的失调会影响到我们的睡眠状况。 一、心情差&#xff0c;压力大&#xff0c;睡不好跟这…

XXL-Job详解(一):组件架构

目录 XXL-Job特性系统组成架构图调度模块剖析任务 “运行模式” 剖析执行器 XXL-Job XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 特性 1、简单&#…

【驱动】串口驱动分析(二)-tty core

前言 tty这个名称源于电传打字节的简称&#xff0c;在linux表示各种终端&#xff0c;终端通常都跟硬件相对应。比如对应于输入设备键盘鼠标&#xff0c;输出设备显示器的控制终端和串口终端。也有对应于不存在设备的pty驱动。在如此众多的终端模型之中&#xff0c;linux是怎么…

信贷专员简历模板

这份简历内容&#xff0c;以信贷专员招聘需求为背景&#xff0c;我们制作了1份全面、专业且具有参考价值的简历案例&#xff0c;大家可以灵活借鉴。 信贷专员简历在线编辑下载&#xff1a;百度幻主简历 求职意向 求职类型&#xff1a;全职 意向岗位&#xff1a;信贷专员 …

Linux:docker的数据管理(6)

数据管理操作*方便查看容器内产生的数据 *多容器间实现数据共享 两种管理方式数据卷 数据卷容器 1.数据卷 数据卷是一个供容器使用的特殊目录&#xff0c;位于容器中&#xff0c;可将宿主机的目录挂载到数据卷上&#xff0c;对数据卷的修改操作立刻可见&#xff0c;并且更新数…

基于SpringBoot的在线视频教育平台的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于在线视频教育平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了在线视频教育平台&#xff0c;它彻底改变了过…