C++——模板初阶
文章目录
- 一.泛型编程
- 二.函数模板
- 1.函数模板的概念
- 2.函数模板的格式
- 3.函数模板的原理
- 4.函数模板的实例化
- (1)隐式实例化
- (2)显式实例化
- 5.模板参数的匹配原
- 三.类模板
- 1.类模板的定义格式
- 2.类模板的实例化
前言:
本章我们将学习模板,正式接触泛型编程。
C++相比于C语言有这么多丰富的接口与类型,都源于泛型编程。本章的内容为模板初阶知识,为接下来的STL学习打下坚实的基础。
一.泛型编程
如何实现一个通用的交换函数(swap)呢?我们已经学过函数重载的使用,函数重载在这种场景下作用很大:
void Swap(int& a, int& b)
{auto tmp = a;a = b;b = tmp;
}void Swap(double& a, double& b)
{auto tmp = a;a = b;b = tmp;
}void Swap(char& a, char& b)
{auto tmp = a;a = b;b = tmp;
}
//...
使用函数重载虽然可以实现,但是有一下几个不好的地方:
- 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
- 代码的可维护性比较低,一个出错可能所有的重载均出错
那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?
- 这就是我们今天要讲到的模板——模板是泛型编程的基础。模板不仅适用于函数,也适用于类。
二.函数模板
1.函数模板的概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
2.函数模板的格式
template<typename T1, typename T2,......,typename TN>
返回值类型 函数名(参数列表)
{//...函数体
}
示例:
template<typename T>
void Swap(T& a,T& b)
{auto tmp = a;a = b;b = tmp;
}
template<class N>
void Swap(N& a, N& b)
{auto tmp = a;a = b;b = tmp;
}
注意:
typename后面的内容不一定是T,可自由指定;typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
3.函数模板的原理
函数模板是一个描述的过程、一幅设计图、一个模板,并不是真正的函数。编译器会根据模板使用特定方式产生具体类型函数。所以其实模板就是将本来应该我们做的重复的事情交给了编译器去做(想想印刷术的原理)。

在编译器编译阶段,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。
比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。
4.函数模板的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
(1)隐式实例化
让编译器根据实参推演模板参数的实际类型。
示例:
template<class T>
T Add(T a, T b)
{return a + b;
}
void Test()
{int a = 10;int b = 100;cout << Add(a, b) << endl;
}

(2)显式实例化
在函数名后的<>中指定模板参数的实际类型。
错误示例:
template<class T>
T Add(T a, T b)
{return a + b;
}void Test()
{int a = 10;double d = 3.14;cout << Add(a, d) << endl;
}
运行结果:

错误原因:
- 因为在编译期间,当编译器看到该实例化时,需要推演其实参类型通过实参
a将T推演为int,通过实参d将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int或者double类型而报错。
正确的做法
①显式实例化:就是在告诉编译器:不用你推演了,我已经指定这个类型了。
template<class T>
T Add(T a, T b)
{return a + b;
}void Test()
{int a = 10;double d = 3.14;cout << Add<int>(a, d) << endl;
}

②使用多个模板参数:
template<class T,class Y>
Y Add(T a, Y b)
{return a + b;
}void Test()
{int a = 10;double d = 3.14;cout << Add(a, d) << endl;
}

注意:
- 在下面情况中,两次调用的
swap函数不是同一个函数!
template<class N>
void Swap(N& a, N& b)
{auto tmp = a;a = b;b = tmp;
}
void Test()
{int a = 10;int b = 100;Swap(a,b);char c1 = 'a';char c2 = 'b';Swap(c1, c2);
}
如下图所示汇编代码,显然两次调用的函数并不是一个函数(一个类型为Swap< int >,一个为Swap< char >)。事实上,虽然我们看不见这两份函数的代码,但是它们实实在在的产生了:

5.模板参数的匹配原
①一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。
template<class T>
T Add(T a, T b)
{return a + b;
}int Add(int a, int b)
{return a + b;
}void Test()
{int a = 10;int b = 100;cout << Add<int>(a, b) << endl;
}
②对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板。
template<class T,class Y>
Y Add(T a, Y b)
{cout << "模板" << endl;return a + b;
}
int Add(int a, int b)
{cout << "非模板" << endl;return a + b;
}
void Test()
{int a = 10;int b = 100;double d = 3.14;cout << Add(a, b) << endl;//使用非模板函数cout << Add(a, d) << endl;//使用模板
}

③模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
三.类模板
1.类模板的定义格式
template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
示例:
template<class T>
class Stack
{
public://...
private:T* _a;size_t _size;size_t _capacity;
};
2.类模板的实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
// Stack类名,Stack<int>是类型
Stack<int> s1;
Stack<double> s2
本文到此结束,码文不易,还请多多支持哦!
相关文章:
C++——模板初阶
文章目录 一.泛型编程二.函数模板1.函数模板的概念2.函数模板的格式3.函数模板的原理4.函数模板的实例化(1)隐式实例化(2)显式实例化 5.模板参数的匹配原 三.类模板1.类模板的定义格式2.类模板的实例化 前言: 本章我们…...
【TOOLS: Linux与windows及linux与linux之间文件传输常用方法及命令】
文章目录 1.1.1 Windows和VirtualBox(Ubuntu)之间文件穿传输方法1.1.2 SCP 文件传输方法1.1.3 FTP 文件传输方法 1.1.1 Windows和VirtualBox(Ubuntu)之间文件穿传输方法 1)设置 virtualbox 中的共享文件夹,用户可以在windows某个盘下创建自己的共享文件…...
【博览群书】《实战大数据》——属于我的第一本大数据图书
文章目录 前言简介目录其他 前言 Hello家人们,博主前不久参加了CSDN图书馆和机械工业出版社联合举办的图书类活动,很荣幸在活动中获得了属于自己的第一本大数据图书,《实战大数据—— 分布式大数据分析处理系统开发与应用》。作为大数据专业…...
【计算机组成原理】实验二
文章目录 实验二 运算器实验一、实验目的二、实验原理三、运算器功能编码四、实验内容任务一 算术运算任务二 逻辑运算任务三 移位运算 实验二 运算器实验 一、实验目的 完成算术、逻辑、移位运算实验,熟悉ALU运算类型的控制位运用。实验仪器:JTHS-A …...
hive数据库hql基础操作02
1.内部表和外部表 默认情况下创建的表就是内部表,Hive拥有该表的结构和文件。换句话说,Hive完全管理表(元数据和数据)的生命周期,类似于RDBMS中的表。当你删除内部表时,它会删除数据以及表的元数据。可以使…...
门电路OD门
漏极开路输出的门电路(OD门) 为了满足输出电平的变换,输出大负载电流,以及实现“线与”功能,将CMOS门电路的输出级做成漏极开路的形式,称为漏极开路输出的门电路,简称OD(Open&#x…...
没有域名,一个服务器Nginx怎么部署多个前端项目
因为没有域名,所以用路径来作区分, 主项目:直接根路由访问该项目,与正常配置无任何差别从项目:此处设置/new路径,为从项目,所有从项目访问路径均要加上/new ①修改Nginx配置文件 Nginx 配置文…...
城市内涝的原因和解决措施,内涝监测预警助力城市防涝度汛
城市内涝是城市化进程中最遇到的自然灾害,城市内涝不仅会对市民生活造成困扰,也会对城市基础设施和经济发展产生不利影响。因此,及时监测城市内涝现象,对于城市管理和城市安全具有重要意义。本文将深入探讨城市内涝的原因以及针对…...
8年测试总结,性能测试问题大全,这些问题你应该认清的...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 响应时间VS吞吐量…...
RabbitMQ集群安装
RabbitMQ集群安装 1.前言 OS: CentOS Linux release 7.9.2009 (Core) 机器: IPnodecpu内存存储10.106.1.241max-rabbitmg-018 核16 G100 G10.106.1.242max-rabbitmg-028 核16 G100 G10.106.1.243max-rabbitmg-038 核16 G100 G 因为操作系统版本是 centos7,所以…...
面试:link和@import的区别
1:link是XHTML标签,除了加载CSS外,还可以加载RSS;import只能加载CSS 2:link引入CSS时,在页面载入时同时加载;import需要页面完全载入后加载,可能会出行闪屏 3:link是XHTML标签,无兼容…...
图片隐写(一)
文件隐藏 binwalk binwalk -e filename foremost foremost filename steghide & stegseek Install sudo apt-get install steghidestegseek Use steghide extract -sf filename -p passwordtime stegseek secret.file aaa.txt dd 文本隐藏 二进制文件末尾 or 文…...
Vivado 下 IP核 之ROM 读写
目录 Vivado 下 IP核 之ROM 读写 1、实验简介 2、ROM IP 核简介 3、ROM IP 核配置 3.1、创建 ROM 初始化文件 3.2、单端口 ROM 的配置 3.3、双端口 ROM 的配置 3.4、ROM IP 核的调用 (1)ROM 顶层模块代码 (2)ROM IP 核仿…...
朗诵素材-《诵四季诗韵,咏师恩师德》
女:中华五千年的悠久历史,孕育了底蕴深厚的民族文化。 男:华夏源远流长的经典诗文, 女:是文化艺苑中经久不衰的瑰宝。 男:在那些脍炙人口的诗句里,凝聚着华光熠熠的民族精魂。 女࿱…...
CHB-麻省理工学院头皮脑电图数据库
数据库介绍 该数据库在波士顿儿童医院收集,包括患有顽固性癫痫发作的儿科受试者的脑电图记录。受试者在停用抗癫痫药物后被监测长达几天,以表征他们的癫痫发作并评估他们手术干预的候选资格。 数据库链接:https://physionet.org/content/chb…...
传输层协议
目录 传输层 端口号 端口号范围划分 认识知名端口号(Well-Know Port Number) netstat pidof UDP协议UDP协议端格式编辑 UDP的特点 面向数据报 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 TCP协议 TCP协议段格式 确认应答(ACK)机制 超时重传机制 连…...
公司新招了个字节拿36K的人,让我见识到了什么才是测试扛把子......
5年测试,应该是能达到资深测试的水准,即不仅能熟练地开发业务,而且还能熟悉项目开发,测试,调试和发布的流程,而且还应该能全面掌握数据库等方面的技能,如果技能再高些的话,甚至熟悉分…...
pytorch rpc如何实现分物理机器的model parallel
因为业务需要,最近接到一项任务,是如何利用pytorch实现model parallel以及distributed training。搜罗了网上很多资料,以及阅读了pytorch官方的教程,都没有可参考的案例。讲的比较多的是data parallel,关于model paral…...
APP服务端架构的演变
大家好,我是易安! 早期2013年的时候,随着智能设备的普及和移动互联网的发展,移动端逐渐成为用户的新入口,各个电商平台都开始聚焦移动端App,如今经历了10年的发展,很多电商APP早已经没入历史的洪…...
EasyRecovery16适用于Windows和Mac的专业硬盘恢复软件
无论你对数据恢复了解多少, 我们将为您处理所有复杂的流程并简化恢复!适用于Windows和Mac的 专业硬盘恢复软件 硬盘数据无法保证绝对安全。有时会发生数据丢失,需要使用硬盘恢复工具。支持恢复不同存储介质数据:硬盘、光盘、U盘/移动硬盘、数…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...
