【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.rhkb.cn/news/206829.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python——— 函数大全

&#xff08;一&#xff09;初识函数 函数是可重用的程序代码块。 函数的作用&#xff0c;不仅可以实现代码的复用&#xff0c;更能实现代码的一致性。一致性指的是&#xff0c;只要修改函数的 代码&#xff0c;则所有调用该函数的地方都能得到体现。 在编写函数时&#xff0…

Linux常用命令----mkdir命令

文章目录 1. 基础概念2. 参数含义3. 常见用法4. 实例演示5. 结论 在Linux操作系统中&#xff0c;mkdir 命令是用来创建目录的基础命令。这个命令简单但极其强大&#xff0c;是每个Linux用户都应当熟悉的工具之一。以下是对mkdir命令的详细介绍&#xff0c;包括其参数含义、常见…

苹果cms搭建教程附带免费模板

准备工作: 一台服务器域名源码安装好NGINX+PHP7.0+MYSQL5.5 安装php7.0的扩展,fileinfo和 sg11,不安装网站会搭建失败。 两个扩展都全部安装好了之后 点击-服务-重载配置 这样我们的网站环境就配置完成啦 下载苹果cms 苹果cms程序github链接:选择mac10!下载即可 http…

Vue批量全局处理undefined和null转为““ 空字符串

我们在处理后台返回的信息&#xff0c;有的时候返回的是undefined或者null&#xff0c;这种字符串容易引起用户的误解&#xff0c;所以需要我们把这些字符串处理一下。 如果每个页面都单独处理&#xff0c;那么页面会很冗余&#xff0c;并且后期如果有修改容易遗漏&#xff0c…

DiSC沟通法,如何提高项目沟通效率?

DISC模型是一种用于理解和改善人际沟通的工具&#xff0c;它可以帮助团队成员更好地理解自己和他人的沟通方式&#xff0c;从而提高团队的沟通效率和协作效率。如果双方没有理解和适应对方的行为风格&#xff0c;往往容易造成误解甚至冲突&#xff0c;从而不利于团队间沟通协作…

vscode集成git

1、首先电脑要安装git 打开git官网地址&#xff1a;Git进行下载&#xff0c;如下图界面&#xff1a; 如图片中描述&#xff1a;一般进入官网后会识别电脑对应系统&#xff08;识别出了我的电脑是Windows系统 。如果未识别到电脑系统&#xff0c;可在左侧选择自己电脑对应的系统…

Influx集群解决方案(Influx Proxy篇)

InFluxDB 集群搭建 本次搭建使用influx proxy 介绍 github地址:https://github.com/chengshiwen/influx-proxy/ Influx Proxy 是一个基于高可用、一致性哈希的 InfluxDB 集群代理服务&#xff0c;实现了 InfluxDB 高可用集群的部署方案&#xff0c; 具有动态扩/缩容、故障恢复…

【MySQL】JDBC编程

&#x1f451;专栏内容&#xff1a;MySQL⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、JDBC工作原理二、JDBC 使用1、准备工作2、使用实例3、手动输入 一、JDBC工作原理 JDBC是Java语言中用于与数据库进行交互…

Panalog 日志审计系统 前台RCE漏洞复现

0x01 产品简介 Panalog是一款日志审计系统&#xff0c;方便用户统一集中监控、管理在网的海量设备。 0x02 漏洞概述 Panalog日志审计系统 sy_query.php接口处存在远程命令执行漏洞&#xff0c;攻击者可执行任意命令&#xff0c;接管服务器权限。 0x03 复现环境 FOFA&#xf…

centos7配置tomcat

简介 Tomcat是一个使用Java编写的开源Web应用服务器,是由Apache Software Foundation管理的一个项目。它是一个轻量级的应用服务器,可以下载、安装和使用,而且还提供了许多高级功能,例如支持Java Servlet、JavaServer Pages (JSP)和JavaServer Faces (JSF) 等JavaEE技术,…

深度解析 Spring Security 自定义异常失效问题:源码剖析与解决方案

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

计算机视觉面试题-03

1、简单介绍一下sigmoid&#xff0c;relu&#xff0c;softplus&#xff0c;tanh&#xff0c;RBF及其应用场景 这里简单介绍几个激活函数及其应用场景&#xff1a; Sigmoid 函数&#xff08;Logistic 函数&#xff09;&#xff1a; 公式&#xff1a; s i g m a ( x ) 1 1 e …

Python生成exe文件

Python如何生成exe文件 在终端执行 pip install pyinstaller 在终端执行pyinstaller E:\fund_data\GetFund.py&#xff0c;运行结束后会在D:\Python\Python311\Scripts\dist\目录下生成GetFund.exe文件 3.双击exe文件运行&#xff0c;如果未出现预期结果&#xff0c;可以把e…

2023.11.23使用flask实现在指定路径生成文件夹操作

2023.11.23使用flask实现在指定路径生成文件夹操作 程序比较简单&#xff0c;实现功能&#xff1a; 1、前端输入文件夹 2、后端在指定路径生成文件夹 3、前端反馈文件夹生成状态 main.py from flask import Flask, request, render_template import osapp Flask(__name__)a…

STM32USART+DMA实现不定长数据接收/发送

STM32USARTDMA实现不定长数据接收 CubeMX配置代码分享实践结果 这一期的内容是一篇代码分享&#xff0c;CubeMX配置介绍&#xff0c;关于基础的内容可以往期内容 夜深人静学32系列11——串口通信夜深人静学32系列18——DMAADC单/多通道采集STM32串口重定向/实现不定长数据接收 …

【Java学习笔记】71 - JDBC入门

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter25/src/com/yinhai/dao_ 一、JDBC概述 1.基本介绍 1. JDBC为访问不同的数据库提供了统一的接口&#xff0c;为使用者屏蔽了细节问题。 2. Java程序员使用JDBC,可以连接任何提供了JDBC驱动…

C++ -- 每日选择题 -- Day2

第一题 1. 下面代码中sizeof(A)结果为&#xff08;&#xff09; #pragma pack(2) class A {int i;union U{char str[13];int i;}u;void func() {};typedef char* cp;enum{red,green,blue}color; }; A&#xff1a;20 B&#xff1a;21 C&#xff1a;22 D&#xff1a;24 答案及解析…

ssm+vue的仓库在线管理系统的设计与实现(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的仓库在线管理系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三…

游戏反Frida注入检测方案

在游戏安全对抗过程中&#xff0c;有不少外挂的实现基于对游戏内存模块进行修改&#xff0c;这类外挂通常会使用内存修改器&#xff0c;除此之外&#xff0c;还有一种门槛相对更高、也更难检测的「注入挂」。 据FairGuard游戏安全数据统计&#xff0c;在游戏面临的众多安全风险…

Apipost推出IDEA插件,代码写完直接调试

IDEA是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。我们在编写完接口代码后需要进行接口调试等操作&#xff0c;一般需要打开额外的调试工具。 今天给大家介绍一款IDEA插件&#xff1a;Api…