C++之 【模板初阶(函数模板与类模板)】
目录
1.泛型编程
2.模板
3函数模板
3.1函数模板的概念
3.2函数模板的格式
3.3函数模板的原理
3.4函数模板的实例化
3.4.1隐式实例化:让编译器根据实参推演模板参数的实际类型
3.4.2显示实例化:在函数名后的<>中指定模板参数的实际类型
3.4.3模板参数的匹配原则
4.类模板
4.1类模板的定义
4.2类模板的格式
4.3类模板的原理
4.3类模板的实例化
1.泛型编程
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;}......
上述代码完成的是不同类型的变量间的交换操作,
可,这看着就有些麻烦,难写,因为,有多少种类型就需要写多少个函数
即使可以ctrl+c/ctrl+v,但仍存在下列问题:
1. 重载的函数仅仅是类型不同,代码复用率比较低,
只要有新类型出现时,就需要用户自己增加对应的函数
2. 代码的可维护性比较低,一个出错可能所有的重载均出错
由此,泛型编程产生了:
通过类型参数(即类型是一个参数)来创建函数或数据结构,
使得同一套代码可以适用于多种数据类型的编程范式就叫做泛型编程
template<typename T>
void Swap(T& x1, T& x2)
{T temp = x1;x1 = x2;x2 = temp;
}
上述代码通过使用模板,将类型参数化,就可以实现多种类型的变量间的交换操作
模板是泛型编程的基础
2.模板

上述浇筑过程中存在一个模具,通过给这个模具中填充不同材料,可以获得不同材料的铸件
C++中的模板就可以被视为一个模具,不同类型可以视为不同材料
本文介绍模板的两种主要形式:函数模板与类模板
3函数模板
3.1函数模板的概念
函数模板是一个与具体数据类型无关的通用函数定义
具体来说就是,函数模板代表了一个函数家族
该函数模板中的类型被参数化,编译器根据实参类型产生函数的特定类型版本
3.2函数模板的格式
// 模板参数列表
template<typename T1, typename T2,......,typename Tn>
// 函数模板定义
返回值类型 函数名(参数列表){}template<typename T>
void Swap(T& x1, T& x2)
{T temp = x1;x1 = x2;x2 = temp;
}
第一行写的是模板参数列表
template是定义模板的关键字,
typename是定义模板参数的关键字,
也可以用class定义模板参数,但不能用struct,如下:
template<class T1, class T2,......,class Tn>第二行开始写函数模板,此时根据需要,将类型参数化
3.3函数模板的原理
函数模板是一个蓝图,不是函数,
它是编译器根据实参类型产生特定类型函数的模具
所以其实模板就是将本来应该我们做的重复的事情交给了编译器

在编译器编译阶段:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此
3.4函数模板的实例化
编译器根据实参类型产生特定类型函数的过程就称为函数模板的实例化
简单来说,函数模板的实例化就是通过函数模板生成一个函数,
函数模板实例化分为:隐式实例化和显式实例化
3.4.1隐式实例化:让编译器根据实参推演模板参数的实际类型
此时,确保实参类型一致即可
template<typename T>
T Add(const T& x1, const T& x2)
{return x1 + x2;
}int main()
{int a = 1, b = 2;double c = 3.0, d = 4.0;Add(a, b);Add(c, d);return 0;
}

这时候,有两种办法:1.强制类型转化
这里需要注意:强制类型转化会产生临时变量,临时变量具有常性
此时参数列表就必须要用const修饰,否则编译不通过。
而最开始用const修饰的初心是防止数据被修改
2.显式实例化
3.4.2显示实例化:在函数名后的<>中指定模板参数的实际类型
Add<int>(a, c);
3.4.3模板参数的匹配原则
1.一个非模板函数可以和一个同名的函数模板同时存在
而且该函数模板还可以被实例化为这个非模板函数
template<typename T>
T Add(const T& x1, const T& x2)
{return x1 + x2;
}int Add(int& x1, int& x2)
{return x1 + x2;
}
这就是上面说的同时存在
int main() {Add(1, 2);Add<int>(1, 2);return 0; }第一次调用的函数,与非模板函数匹配,直接调用非模板函数,编译器不需要特化
第二次调用的函数是编译器特化的Add版本
这就是上面说的实例化
2.对于非模板函数和同名函数模板的调用,
如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例
如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
int main() {Add(1, 2);Add(1, 2.0);return 0; }第一次调用的函数,与非模板函数匹配,直接调用非模板函数,编译器不需要特化
第二次调用的函数是编译器特化的Add版本,因为此时才更加匹配
3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
在这里,编译器无法推导出T的具体类型,不会自动转换a或者c的类型
除非显式指定或者强制类型转换,不然编译器会直接报错
Add<int>(a, c); Add(a, (int)c);void foo(double d) {} foo(42); // int→double隐式转换普通函数就支持自动类型转换
模板函数是类型生成机制,而普通函数是类型匹配机制。模板在编译期"雕刻"类型,普通函数在运行时"适配"类型。这种设计使得模板既能保持类型安全,又能通过特化和重载提供灵活性,而普通函数则通过隐式转换维持编程的便利性 --------文心一言
4.类模板
4.1类模板的定义
类模板是一个与具体数据类型无关的通用类定义
具体来说就是,类模板代表了一个类家族
该类模板中的类型被参数化,编译器根据实参类型产生类的特定类型版本
4.2类模板的格式
template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
第一行写的是模板参数列表
template是定义模板的关键字,
typename是定义模板参数的关键字,
也可以用class定义模板参数,但不能用struct,如下:
template<class T1, class T2,......,class Tn>第二行开始写类模板,此时根据需要,将类型参数化
template <class T>Vector<T>::~Vector(){if(_pData)delete[] _pData;_size = _capacity = 0;}
注意:类模板中函数放在类外进行定义时,需要加模板参数列表,同时指定类模板
4.3类模板的原理
类模板不是一个类,类模板的原理与函数模板的原理相同,
就是将本来应该我们做的重复的事情(识别参数类型)交给了编译器
4.3类模板的实例化
简单来说,类模板的实例化就是通过模板生成一个具有特定数据类型的类
// Vector类名,Vector<int>才是类型Vector<int> s1;Vector<double> s2;
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类
总结:
对于普通类来说,类名(类模板名)与类型一致
对于模板类来说,类名就是类模板名,类型还需要指定参数列表
相关文章:
C++之 【模板初阶(函数模板与类模板)】
目录 1.泛型编程 2.模板 3函数模板 3.1函数模板的概念 3.2函数模板的格式 3.3函数模板的原理 3.4函数模板的实例化 3.4.1隐式实例化:让编译器根据实参推演模板参数的实际类型 3.4.2显示实例化:在函数名后的<>中指定模板参数的实际类型 3.…...
博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解
博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解 1. 引言:为什么需要均衡精炼? 在博弈论中,纳什均衡是分析策略互动的核心工具,但其存在一个显著缺陷:无法排除不合理的均衡。例如࿰…...
在线教育网站项目第四步:deepseek骗我, WSL2不能创建两个独立的Ubuntu,但我们能实现实例互访及外部访问
一、说明 上一章折腾了半天,搞出不少问题,今天我们在deepseek的帮助下,完成多个独立ubuntu24.04实例的安装,并完成固定ip,实践证明,deepseek不靠谱,浪费我2个小时时间,我们将在下面实…...
在刀刃上发力:如何精准把握计划关键节点
关键路径分析是项目管理中的一种重要方法,它通过在甘特图中识别出项目中最长、最关键的路径,来确定项目的最短完成时间。 关键路径上的任务都是项目成功的关键因素,任何延误都可能导致整个项目的延期。关键路径分析对于项目管理者来说至关重要…...
组合总和||
1.给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 #include <bits/stdc.h> using namespace std; vector<vector<int>> result; vec…...
OpenCV图像拼接(2)基于羽化(feathering)技术的图像融合算法拼接类cv::detail::FeatherBlender
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::detail::FeatherBlender 是 OpenCV 中用于图像拼接的一个类,它属于 stitching 模块的一部分。这个类实现了基于羽化(…...
MediaPipe软件包如何构建和安装
MediaPipe 是一个由 Google 开发的多媒体机器学习框架,支持多种平台(如 Android、iOS、桌面等)。以下是构建和安装 MediaPipe 的步骤: 1. 环境准备 确保系统满足以下要求: 操作系统: Ubuntu (推荐 18.04 或 20.04)、…...
分享下web3j 常见用法
转账 fun sendEthTransaction(privateKey: String,toAddress: String,amount: BigDecimal) {//chainIdval chainId:Long 1//url 可以从https://chainlist.org/里面获取可用节点//eth转账,bnb同理,但需发送到bnb对应节点val url "https://xxx"…...
连接chatgpt的桌面语音助手
要创建一个连接到 ChatGPT 的桌面语音助手,可以使用 Python 编写一个程序来实现语音识别、与 ChatGPT API 交互以及语音合成的功能。以下是一个完整的解决方案和技术实现步骤: 所需工具和库 语音识别 使用 speech_recognition 库捕获用户的语音输入。需要…...
systemctl restart 和 systemctl reload 和 systemctl daemon-reload 对比 笔记250322
systemctl restart 和 systemctl reload 和 systemctl daemon-reload 对比 以下是 systemctl restart、systemctl reload 和 systemctl daemon-reload 的对比总结: 命令作用对象行为适用场景对服务的影响systemctl restart 服务名具体服务强制停止服务,…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能示例9,TableView15_09带排序的导出表格示例
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
spring boot 登入权限RBAC模式
首先准备好5张表 user_info表,用户的信息表 role表,角色表(比如超级管理员、管理员、审核员、采购......) 创建user_role表,user_info表,role表的中间表 注意了,role_id和user_id是 u…...
调用API拿到的值——存储方式
1.响应结果示例: "purposeTagList":["稳中向好及进中提质"] 2.数据库中定义的 3.值的获取: F1 JsonNode purposeTagListNode dataNode.path("purposeTagList");if (purposeTagListNode.isArray()) {StringBuilder purp…...
【用 Trace读源码】PlanAgent 执行流程
前提条件 在 Trae 中打开 OpenManus 工程,使用 build 模式,模型选择 claude-sonnet-3.7 提示词 分析 agent/planning.py 中 main 方法及相关类的执行流程,以流程图的方式展示PlanningAgent 执行流程图 以下流程图展示了 PlanningAgent 类…...
第一讲 | 解锁C++编程能力:基础语法解析
C入门基础 一、C的第一个程序二、命名空间三、C输入&输出四、缺省参数/默认参数五、函数重载六、引用1.引用的特性2.引用的使用引用做返回值场景 3.const引用只有指针和引用涉及权限放大、缩小的问题,普通变量没有 4.指针和引用的关系 七、inline八、nullptr 一…...
LeetCode 热题 100_划分字母区间(80_763_中等_C++)(贪心算法(求并集))
LeetCode 热题 100_划分字母区间(80_763) 题目描述:输入输出样例:题解:解题思路:思路一(贪心算法(求交集)): 代码实现代码实现(思路一(贪心算法(求…...
C++ --- 多态
1 多态的概念 多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态),这⾥我们重点讲运⾏时多态,编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主要就是我…...
HAL库中使用空闲中断+DMA接收数据,接收失败的问题
问题: 串口屏与单片机通过串口(USART1)进行通信,调试时发现问题,现象如下: 手动页面的几个文本,输入的数字不会显示出来,比如初始值为0,输入200,200会一闪而…...
【STM32实物】基于STM32的扫地机器人/小车控制系统设计
基于STM32的扫地机器人/小车控制系统设计 演示视频: 基于STM32的扫地机器人小车控制系统设计 简介:扫地机器人系统采用分层结构设计,主要包括底层硬件控制层、中间数据处理层和上层用户交互层。底层硬件控制层负责对各个硬件模块进行控制和数据采集,中间数据处理层负责对采…...
【Scrapy】Scrapy教程8——处理子链接
通过前面几篇文章,已经了解了如何去爬取网页内容并存储到数据库,但是目前只是存储了一个页面的内容,现在想要获取每篇文章链接内的文章内容,我们来看看怎么获取。 生成新请求 首先我们肯定要先拿到链接,所以第一步都获取文章标题和链接肯定少不了,然后再爬取获取到到子…...
使用pycel将Excel移植到Python
1.适用需求 有些工作可能长期适用excel来进行公式计算,当需要把工作流程转换为可视化界面时,开发人员不懂专业逻辑,手动摸索公式很大可能出错,而且费时费力 2.可用工具及缺点 pandas 方便进行数据处理,支持各种格…...
学习应用层
应用层概述 客户/服务器方式(C/S)和对等方式(P2P) 动态主机配置协议DHCP 客户/服务器方式 DHCP报文会被封装成为UDP用户数据报,DHCP服务器端口号是UDP67,用户是UDP68。 广播发送,是因为并不知道…...
Doris官网上没有的一些Fe参数了,都在源码中
一、FE配置源码 apache-doris-src\fe\fe-common\src\main\java\org\apache\doris\common\Config.java 二、BE配置源码 apache-doris-src\be\src\common\config.cpp 三、FE源码 package org.apache.doris.common;public class Config extends ConfigBase {ConfField(descri…...
蓝桥杯算法精讲:二分查找实战与变种解析
适合人群:蓝桥杯备考生 | 算法竞赛入门者 | 二分查找进阶学习者 目录 一、二分查找核心要点 1. 算法思想 2. 适用条件 3. 算法模板 二、蓝桥杯真题实战 例题1:分巧克力(蓝桥杯2017省赛) 例题2:砍竹子࿰…...
C++脚本化方案调研
1 什么是脚本化 脚本化(Scripting)是指将脚本语言嵌入到主程序(C等编译型语言)中,通过以下方式扩展程序能力: 动态逻辑控制:通过脚本实现运行时逻辑调整,无需重新编译主程序&#x…...
蓝桥杯(N皇后问题)------回溯法
题目描述 在 NN 的方格棋盘放置了 N 个皇后,使得它们不相互攻击(即任意 2 个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成 45 角的斜线上。你的任务是,对于给定的 N,求出有多少种合法的放置方法…...
再探C语言(1)
温馨提示: 学C语言就像玩《掘地求升》——你以为懂了语法就能通关? 不!编译器会用铁锤教你做人!(╯‵□′)╯︵┻━┻ 🐱Part 1:sizeofの跨平台迷惑行为 Q1. 不同环境下sizeof(int)的结果 运行环境结果&a…...
高项第十三章——项目资源管理
什么是资源管理?项目资源管理包括识别、获取和管理所需资源以成功完成项目的各个过程。 本过程关注两类资源:实物资源包括设备、材料、设施和基础设施 团队资源或人员指的是团队的人力资源 13_1 项目资源管理基础 项目团队是执行项目工作,…...
C/C++转换为字符串宏和字符串拼接宏的综合使用
本文内容参考: C/C++ 宏拼接和宏展开为字符串 - DoubleLi - 博客园 特此致谢! 1. 转换为字符串宏与字符串拼接宏 (1)转换为字符串宏 转换为字符串的宏为: #define STR(x) #x //转字符串 (2)字符串拼接宏 字符串拼接的宏为: #define CONCAT(x,y) x##y //拼接 2…...
Linux:xxx is not in the sudoers file. This incident will be reported.
报错 xxx is not in the sudoers file. This incident will be reported.解决方式 切换到root用户下操作 # 1、修改/etc/sudoers文件为可修改,默认是只读的 ls -lh /etc/sudoers -r--r----- 1 root root 4.3K Dec 1 01:45 /etc/sudoerschmod uw /etc/sudoersls…...


