【C++】什么是模板?怎样使用模板?

👀樊梓慕:个人主页

 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》

🌝每一个不曾起舞的日子,都是对生命的辜负


目录

前言

1.函数模板

1.1函数模板概念

1.2函数模板格式

1.3函数模板的实例化

1.4模板参数的匹配原则

2.类模板

2.1引入

2.2类模板格式

2.3类模板的实例化


前言

在之前的学习中,我们可以利用函数重载实现一些“各种类型通用”的函数,比如交换函数swap,但这样一来代码的复用率很低并且他们仅仅是类型不同而已,每当有新的类型需求时,我们又需要增加新的函数,如何解决这一问题呢?


欢迎大家📂收藏📂以便未来做题时可以快速找到思路,巧妙的方法可以事半功倍。

=========================================================================

GITEE相关代码:🌟fanfei_c的仓库🌟

=========================================================================


1.函数模板

1.1函数模板概念

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

1.2函数模板格式

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}

如:

template<typename T> //template、typename关键字
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}

 注意:typename也是关键字,可以使用class,但不能使用struct


模板实质上只是编译器识别并产生特定具体类型函数的模具,也就是说是编译器替我们实现了具体的函数。


1.3函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。

模板参数实例化分为:隐式实例化显式实例化

(1)隐式实例化:让编译器根据实参推演模板参数的实际类型

请思考:会不会出现推演不出来的情况呢?

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{int a1 = 10, a2 = 20;double d1 = 10.0, d2 = 20.0;Add(a1, a2);Add(d1, d2);/*该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅Add(a1, d1);*/// 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化Add(a, (int)d);return 0;
}

一定要避免出现歧义,要明确了解几个模板参数,几个推演的类型等,否则就会出现问题。


(2)显式实例化:在函数名后的<>中指定模板参数的实际类型

int main(void)
{int a = 10;double b = 20.0;// 显式实例化Add<int>(a, b);//若有两个模板参数就<int,double>return 0;
}

 如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。


1.4模板参数的匹配原则

非模板函数和同名的函数模板同时存在,应该调用哪个?

// 专门处理int的加法函数
int Add(int left, int right)
{return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{return left + right;
}
void Test()
{Add(1, 2); // 与非模板函数匹配,编译器不需要特化Add<int>(1, 2); // 调用编译器特化的Add版本
}

优先调用非模板函数,有现成的就用现成的 。

前面说过,模板实际上只是编译器帮我们生成了,那既然有现成的当然就用现成的咯。

另外如果模板可以产生一个具有更好匹配的函数,那么就选择模板,有更合适的就用更合适的。  


模板函数不允许自动类型转换,但普通函数可以进行自动类型转换


2.类模板

2.1引入

在之前学习数据结构时,我们是利用typedef来确定该数据结构要存储的数据类型的,但这样有很明显的弊端,每有一种新的数据类型的需求,你就得新实现一个,这跟函数重载所遇到的尴尬是一样的,那函数是利用函数模板来解决,类就用类模板来解决好了。

2.2类模板格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};

比如:

// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>
class Vector
{
public:Vector(size_t capacity = 10): _pData(new T[capacity]), _size(0), _capacity(capacity){}// 使用析构函数演示:在类中声明,在类外定义。~Vector();void PushBack(const T& data);void PopBack();// ...size_t Size() { return _size; }T& operator[](size_t pos){assert(pos < _size);return _pData[pos];}
private:T* _pData;size_t _size;size_t _capacity;
};
// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{if (_pData)delete[] _pData;_size = _capacity = 0;
}

注意:声明定义放一个文件, 否则会报错 


2.3类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;

比如:

下面哪种构造的写法是对的?

  • Stack()
  • Stack<T>()

 Stack()这种写法是对的,因为构造函数与类名相同,不是与类型相同。


=========================================================================

如果你对该系列文章有兴趣的话,欢迎持续关注博主动态,博主会持续输出优质内容

🍎博主很需要大家的支持,你的支持是我创作的不竭动力🍎

🌟~ 点赞收藏+关注 ~🌟

========================================================================= 

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

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

相关文章

神奇的世界(高斯核是唯一可以产生多尺度空间的线性核研究总结,两个高斯公式的联系,和推导)

放大缩小其实在现实世界中不存在。 也就是说尺度是不存在的。 比如树的长大&#xff0c;人的长大&#xff0c;从来就不是放大能解释的。 但你发现&#xff0c;这种事情存在于人的眼睛当中&#xff0c;光线真是神奇的东西。 但现实的东西是不存在放大缩小的&#xff0c;只有…

createElement

createElement 逻辑&#xff1a;回到mountComponent函数的过程&#xff0c;至此已经知道vm._render是如何创建了一个VNode&#xff0c;接下来就是要把这个 VNode 渲染成一个真实的DOM并渲染出来&#xff0c;这个过程是通过vm._update完成的&#xff0c;接下来分析一下这个过程…

共筑关基安全防线,开源网安加入中关村华安关键信息基础设施安全保护联盟

近日&#xff0c;开源网安正式加入“中关村华安关键信息基础设施安全保护联盟”&#xff08;以下简称&#xff1a;关保联盟&#xff09;成为会员单位&#xff0c;进一步加强与行业内重要机构、企业的协同合作&#xff0c;推动关键信息基础设施安全保护领域的生态建设。 未来&am…

主机怎么通过命令行方式向虚拟机传输文件

这是几个月前遇到的问题了&#xff0c;那时候想着要记录下来&#xff0c;但后来忙忘了&#xff0c;这次想起来了&#xff0c;于是记录一下。 之前打靶场的时候需要将netcat-win32-1.12放入虚拟机的/var/www/html下&#xff0c;但是我虚拟机无法上网&#xff0c;也就是说无法直…

[每周一更]-(第74期):Docker-compose 部署Jenkins容器-英文版及错误纠错

1、前文概要 通过物理机部署Jenkins前文已经讲过&#xff08;地址&#xff1a;[Jenkins] 物理机 安装 Jenkins&#xff09;&#xff0c;也已经公司内部平稳运行若干年&#xff0c;考虑到容器化的使用场景&#xff0c;部分项目都采用容器运行&#xff0c;开始考虑部署容器化的J…

RK3568 android11 实现双路I2C触摸 --GT9xx

一&#xff0c;GT911 触摸屏简介 它的接口类型为 I2C &#xff0c;供电电压和通讯电压均为 3.3V 。这款电容触摸屏内置了上拉电阻&#xff0c;这意味着我们的开发板上与该触摸屏的接口处不需要设置上拉电阻。关于线序&#xff0c;同样是 GT911 &#xff0c;不同批次的器件都有…

U-Net及其变体在医学图像分割中的应用研究综述

U-Net及其变体在医学图像分割中的应用研究综述 论文来自&#xff1a;中国生物医学工程学报 2022 摘 要&#xff1a; 医学图像分割可以为临床诊疗和病理学研究提供可靠的依据&#xff0c;并能辅助医生对病人的病情做出准确的判断。 基于深度学习的分割网络的出现解决了传统自动分…

数据结构与算法(三)贪心算法(Java)

目录 一、简介1.1 定义1.2 基本步骤1.3 优缺点 二、经典示例2.1 选择排序2.2 背包问题 三、经典反例&#xff1a;找零钱3.1 题目3.2 解答3.3 记忆化搜索实现3.4 动态规划实现 一、简介 1.1 定义 贪心算法&#xff08;Greedy Algorithm&#xff09;&#xff0c;又名贪婪法&…

串口波形延时问题再次故障测试分析

先放电路图吧 这个延时问题测试了很多天&#xff0c;怎么感觉总是有没有想到的问题可以测试&#xff0c;总是有原件可以替换改善问题&#xff0c;再次测试了三极管的C脚波形&#xff1a; 从上到下的3个波形分别是MCU出来的波形&#xff0c;经过三极管反向的波形&#xff0c;…

2.ORB-SLAM3中如何从二进制文件中加载多地图、关键帧、地图点等数据结构

目录 1 为什么保存&加载(视觉)地图 1.1 加载多地图的主函数 1.2 加载各个地图 Atlas::PostLoad 1.3 加载关键帧及地图点Map::PostLoad 1.4 恢复地图点信息 MapPoint::PostLoad 1.5 恢复关键帧信息KeyFrame::PostLoad 1 为什么保存&加载(视觉)地图 因为我们要去做导…

容器虚拟化原理

目录 容器简介容器技术优缺点容器的组成基本技术namespace创建namespace的三种方法PID namespaceIPC namespacemount namespacenetwork namespaceUTC namespace cgroup(control group)rootfs镜像分层 容器创建原理 容器简介 容器是一种打包应用及其运行环境的方式&#xff0c;…

抽象类的使用—模板设计模式 Java

模板设计模式 一、引入二、改进 一、引入 需求 ① 有多个类&#xff0c;完成不同的任务 job ② 要求统计得到各自完成任务的时间 ③ 请编程实现 >最容易想到的方法&#xff0c;写类&#xff0c;统计时间 AA BB中的 job 方法中是有重复的。 >改进1&#xff1a;每个类中&…

SpringBoot整合EasyExcel实现复杂Excel表格的导入导出功能

文章目录 &#x1f389;SpringBoot整合EasyExcel实现复杂Excel表格的导入&导出功能 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;该系列文章专栏&#xff1a;架构设计&#x1f4dc;其他专栏&#xff1a;Java学习路线 Jav…

集成IDE开发环境,Java开发工具IntelliJ IDEA 2023中文

IntelliJ IDEA 2023是一款功能强大的软件&#xff0c;其为程序员提供了一款先进的集成开发环境。它以智能、高效和人性化为主要特点&#xff0c;致力于提高开发人员的生产力&#xff0c;帮助程序员更快、更好地编写代码。IntelliJ IDEA 2023支持多种语言和框架&#xff0c;包括…

继承JsonSerializer+注解实现自定义数据脱敏方案

1、数据脱敏 数据脱敏是一种保护隐私数据的技术&#xff0c;通过将敏感信息转化为非敏感信息来实现对数据的保护&#xff0c;以保护敏感隐私数据的可靠性和安全性。 数据脱敏可以分为可恢复和不可恢复两类: 可恢复类可以通过一定的方式恢复成原来的敏感数据。不可恢复类则无…

村村通工程(Kruskal算法)/最小生成树Kruskal算法【数据结构】

村村通工程&#xff08;Kruskal算法&#xff09; 题目描述 "村村通"是国家一个系统工程&#xff0c;其包涵有&#xff1a;公路、电力、生活和饮用水、电话网、有线电视网、互联网等等。 村村通公路工程&#xff0c;是国家为构建和谐社会&#xff0c;支持新农村建设…

【Shell】Shell基础学习

一、shell脚本 (1)第一个shell脚本 #!/bin/bash #this is a comment echo "hello world"一个shell脚本永远以“#!”开头,这是一个脚本开始的标记,它是告诉系统执行这个文件需要用某个解释器,后面的/bin/bash就是指明解释器的具体位置。 “#”开头是注释 …

P8A003-系统加固-系统管理员账户安全

【预备知识】 Administrator 原意为管理人或行政官员或遗产管理人&#xff0c;在计算机名词中&#xff0c;它的意思是系统超级管理员或超级用户。但是在Windows系统中此用户名只在安全模式中使用。 【实验步骤】 网络拓扑&#xff1a;server2008-basic windows server 2008 …

LeetCode [简单]118. 杨辉三角

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 public class Solution {public IList<IList<int>> Generate(int numRows) {List<IList<int>> res new …

交流负载测试使用场景

交流负载测试是一种在特定环境下&#xff0c;对电力设备、汽车电子部件&#xff0c;工业自动化设备、网络设备、家电产品&#xff0c;航空航天设备以及医疗器械等产品进行测试的方法&#xff0c;该测试的目的是评估这些设备在实际运行条件下的性能和可靠性。 1电力设备测试 交…