【C++精华铺】8.C++模板初阶
目录
1. 泛型编程
2. 函数模板
2.1 函数模板的概念及格式
2.2 函数模板的原理
2.3 模板的实例化
2.4 模板参数的匹配原则
3. 类模板
3.1 类模板格式
3.2 类模板的实例化
1. 泛型编程
什么是泛型编程?泛型编程是避免使用某种具体类型而去使用某种通用类型来进行程序编写的方式,依次来复用某段代码而避免大规模功能相似重复冗余的代码。下面的代码如果想用泛型编程该如何实现。
int add(int a,int b)
{return a + b;
}
double add(double a, int b)
{return a + b;
}
double add(int a, double b)
{return a + b;
}
马云有次说了这么一句话:“世界是懒人创造的,懒不是傻懒,如果你想少干,就要想出懒的方法。 要懒出风格,懒出境界。”C++必然也是有风格有境界的,所以C++中设计了模板实现了泛型编程。
2. 函数模板
2.1 函数模板的概念及格式
模板就是一种模具,通过给这个模具中放不同的材料(类型),来获得不同材料的产品,以此来提高我们的工作效率。而函数模板就是某个函数的模具,与类型无关,在使用的时候参数化,在我们给出特定类型就会生成特定类型的版本。
函数模板的格式:
template<typename T1, typename T2 ...typename Tn>
返回值类型 函数名(形参列表)
{
//函数体
}
根据这个函数的模板我们就可以实现上述add函数的模板:
template<typename L, typename R,typename RET>
RET add(L l, R r)
{return l + r;
}
注:typename是用来定义模板参数的关键字,也可以用class代替。
2.2 函数模板的原理
函数模板本身不是函数,而是一个模具,当我们传入实际类型的时候编译器会根据我们传入的实参类型来推演生成对应类型的函数进行调用。
2.3 模板的实例化
当我们将类型传入模板来生产函数的时候,称之为模板的实例化,模板的实例化分为隐式实例化和显式实例化。
1. 隐式实例化:隐式实例化就是我们不去指定类型,让编译根据我们传入的实参判断其类型传入模板参数列表进行实例化。如下:
template<typename L, typename R>
int add(L l, R r)
{return l + r;
}
int main()
{int a = 0, b = 1;cout << add(a, b) << endl; //根据我传入的a和b自动判断类型进行模板实例化。
}
细心的同学发现,这里我将原来的代码中 typename RET 删掉了,原因就是模板不会对函数的返回值类型进行自动判断,而需要我们手动指定(也就是显式实例化)。
2. 显式实例化:显式实例化就是我们手动向模板传递类型,然后由编译器进行实例化。显式实例化的格式为:
函数名<类型1,类型2,...>(实参列表);
如:
template<typename L, typename R, typename RET>
RET add(L l, R r)
{return l + r;
}
int main()
{int a = 0, b = 1;cout << add<int,int,int>(a, b) << endl;
}
上述代码我们传进去的 a和b的类型与模板参数类型是匹配的,如果不匹配的话编译器会进行隐式类型转化,如果转化失败就报错。如下:
类型转换成功:
template<typename L, typename R, typename RET>
RET add(L l, R r)
{return l + r;
}
int main()
{double a = 0.1;int b = 1;cout << add<int,int,int>(a, b) << endl; //a:double类型隐式转换成int类型
}
输出:
类型转化失败:
template<typename L, typename R, typename RET>
RET add(L l, R r)
{return l + r;
}class Date
{//
};
int main()
{int a = 0, b = 1;cout << add<int,Date,int>(a, b) << endl; //a:类型转化失败
}
输出:
E0304 没有与参数列表匹配的 函数模板 "add" 实例
2.4 模板参数的匹配原则
一个函数的模板函数可以与非模板函数同时存在,并且在没有显式实例化且类型匹配的情况下会优先匹配非模板函数,如果是显式实例化才会调用模板,如下。
template<class T>
void swap(T& a, T& b)
{std::swap(a, b);std::cout << "我是模板 ";std::cout << a << ' ' << b << std::endl;}
void swap(int& a, int& b)
{std::swap(a, b);std::cout << "我是非模板 ";std::cout << a << ' ' << b << std::endl;}
int main()
{int a = 1, b = 2;std::cout << a << ' ' << b << std::endl;swap(a, b); //类型匹配优先调用非模板函数swap<int>(a, b); //调用模板实例化
}
输出:
当我们没有去写模板的时候,函数发生类型不匹配可能会进行隐式类型转换,但是有了模板之后就不会发生隐式类型转化,而是使用模板实例化出来一个更为合适的函数。如下:
没有模板时会发生隐式实例化:
void test(int a, int b)
{std::cout << "我不是模板" << std::endl;
}int main()
{test(2, 2.0);//2.0发生隐式类型转化成int;
}
输出:
存在模板不会发生隐式类型转化,而是使用模板实例化出来一个更为合适的函数:
template<class T1,class T2>
void test(T1 a, T2 b)
{std::cout << "我是模板" << std::endl;
}
void test(int a, int b)
{std::cout << "我不是模板" << std::endl;
}
int main()
{test(2, 2.0);//不发生隐式类型转化而是隐式实例化模板
}
输出:
3. 类模板
3.1 类模板格式
和函数模板一样,类模板是类的一个模具,类模板格式如下:
template<class T1,class T2,class T3,...class Tn>
class 类模板名
{
//类体
};
我们普通类是可以声明和定义分离的,如果类模板要实现声明和定义分离,那么在定义的时候也要加上模板声明。如:
template<class T1, class T2>
class A
{~A(); //声明
};template<class T1,class T2>
A<T1, T2>::~A() //定义
{//...
}
3.2 类模板的实例化
类模板的实例化和函数模板相同,需要在类名后加上尖括号并且指定类型。注:模板名不是类,实例化后才是一个类。
template<class T>
class Date
{//..
};
int main()
{Date<int>;
}
相关文章:

【C++精华铺】8.C++模板初阶
目录 1. 泛型编程 2. 函数模板 2.1 函数模板的概念及格式 2.2 函数模板的原理 2.3 模板的实例化 2.4 模板参数的匹配原则 3. 类模板 3.1 类模板格式 3.2 类模板的实例化 1. 泛型编程 什么是泛型编程?泛型编程是避免使用某种具体类型而去使用某种通用类型来进行…...

离谱的Bug
离谱的 Bug Bug 情况发现 Bug修改 Bug其他感受历史 Bug火星Spirit号Mars Global Surveyor任务 Bug 情况 有一次,我在开发一个网页应用程序时,遇到了一个令人目瞪口呆的Bug。这个Bug出现在一个特定的页面上,当用户点击某个按钮时,…...

leetcode 322. 零钱兑换
本题属于完全背包问题,但要求最少的硬币个数。于是设定dp数组的含义dp[i]:总金额为i时,能凑成i的最少硬币个数。 需要注意初始化dp数组时,除0以外的其他地方需要初始化为INT_MAX以保证在递推过程中能被正确的覆盖。 代码如下: …...

(二)结构型模式:6、外观模式(Facade Pattern)(C++实例)
目录 1、外观模式(Facade Pattern)含义 2、外观模式的UML图学习 3、外观模式的应用场景 4、外观模式的优缺点 5、C实现外观模式的简单实例 1、外观模式(Facade Pattern)含义 外观模式(Facade Pattern)…...

docker的资源控制管理——Cgroups
目录 一、对CPU使用率的控制 1.1 CPU 资源控制 1.2 cgroups有四大功能 1.3 设置cpu使用率上限 查看周期限制和cpu配额限制 进行cpu压力测试然后修改每个周期的使用cpu的时间,查看cpu使用率 1.4 设置cpu资源占用比(设置多个容器时才有效…...

less学习语法
1.CSS函数的补充 1.rgb/rgba/translate/rotate/scale 2.非常好用的css函数: var:使用css定义的变量calc:计算css值,通常用于计算元素的大小或位置blur:毛玻璃(高斯模糊)效果gradient:颜色渐变函数 var:定义变量 css中可以自定…...

在 SHELL 脚本中调用另一个 SHELL 脚本(报错: go: not found)
文章目录 在 SHELL 脚本中调用另一个 SHELL 脚本(报错: go: not found)在 SHELL 脚本中调用另一个 SHELL 脚本一个脚本sudo调另外一个脚本,报错(报错: go: not found) 在 SHELL 脚本中调用另一个…...

07微服务的事务管理机制
一句话导读 在单体应用程序中,事务通常是在单个数据库或单个操作系统中管理的,而在微服务架构中,事务需要跨越多个服务和数据库,这就使得事务管理变得更加复杂和困难。 目录 一句话导读 一、微服务事务管理的定义和意义 二、微…...

CS5523规格书|MIPI转EDP方案设计|替代LT8911芯片电路原理|ASL集睿致远CS替代龙讯
ASL芯片(集睿致远) CS5523是一款MIPI DSI输入,DP/e DP输出转换芯片,可pin to pin替代LT8911龙讯芯片。 MIPI DSI 最多支持 4 个通道,每个通道的最大运行速度为 1.5Gps。对于DP 1.2输出,它支持1.62Gbps和2.…...

【制作npm包5】npm包制作完整教程,我的第一个npm包
制作npm包目录 本文是系列文章, 作者一个橙子pro,本系列文章大纲如下。转载或者商业修改必须注明文章出处 一、申请npm账号、个人包和组织包区别 二、了解 package.json 相关配置 三、 了解 tsconfig.json 相关配置 四、 api-extractor 学习 五、npm包…...

QT:定时器事件
定时器第一种办法: 1.利用事件timerEvent,在帮助文档中找到该字段:[override virtual protected] void QTimer::timerEvent(QTimerEvent *e) 重写该虚函数 //重写定时器事件void timerEvent(QTimerEvent *e);2.启动定时器startTimer(1000); …...

GitHub Actions自动化部署+定时百度链接推送
前言 最近用VuePress搭建了一个静态网站,由于是纯静态的东西,每次修改完文章都要重新打包上传很是麻烦。虽然vuepress-theme-vdoing主题作者提供了GitHub Actions自动化部署的教程文章,但是过于简陋且是19年发布的。。 1. 创建一个GitHub仓…...

PHP学习心得:如何编写可维护的代码
PHP学习心得:如何编写可维护的代码 引言: 在现代的软件开发中,编写可维护的代码是非常重要的。无论是个人项目还是团队项目,可维护的代码可以提高开发效率,减少维护成本,确保代码的质量和可扩展性。本文将…...

使用vscode进行远程调试
官方调试手册:vscode官方调试手册 1.安装python扩展 如果是远程连接的话,一定要在ssh上启用扩展。不然创建基于python的配置文件时就会提示,无python扩展。 2.新建配置文件,并修改参数 点击左侧第四个按钮,运行与调试…...

LinuxC编程——进程
目录 一、概念1.1 程序1.2 进程 二、特点⭐⭐⭐三、进程段四、进程分类五、进程状态六、进程状态转换图七、函数接口1. 创建子进程2. 回收进程资源3. 退出进程4. 获取进程号 八、守护进程 一、概念 进程和程序是密不可分的两组概念,相对比,便于理解。 1.…...
深入理解设计模式-结构型之适配器
适配器模式(Adapter Pattern): 适配器模式用于将一个类的接口转换成另一个类的接口,以使两者能够一起工作。适配器模式通常用于处理已经存在的类,让它们能够与其他类协同工作,而不需要修改原始类的代码。&…...

桥梁结构健康监测系统,智能预警降低桥梁安全隐患
桥梁通常位于现代综合交通网络中的咽喉部位,对区域经济发展起着重要的推进作用,然而在为社会经济发展做出巨大贡献的同时,它们不可避免地会在荷载作用、环境侵蚀和自然灾害等影响下出现材料腐蚀劣化、结构损伤开裂、性能退化和功能失效等损伤…...

夏威夷等全球多地深陷「末日狂烧」,关键时刻 AI 监测能否跑赢野火?
内容一览:当地时间 8 月 8 日,美国夏威夷州突发野火,当地居民和游客不得不跳入太平洋中躲避火势。截至 8 月 17 日,这场野火已经造成110 人死亡,超过 1000人失踪。与此同时,美国、加拿大、法国等地也正遭遇…...

解决多模块内核心模块有接口打包成jar后被依赖并调用遇到的问题(springcloud集成ruoyi.quartz)
项目准备开发个新功能,刚好很喜欢ruoyi写的任务调度,因此想到了集成ruoyi.quartz模块 ,遇到了很多问题: 首先因为ruoyi.quartz模块依赖了ruoyi.common模块,因此第一步我需要把common模块一部分依赖项复制到了quartz模块内…...
【kubernetes系列】Kubernetes之Kubelet运行机制和状态更新机制
Kubelet运行机制 Kubelet是Kubernetes中的一个重要组件,在每个 Node 节点上都会启动 kubelet 服务。 该服务主要用于处理 Master 节点下发到本节点的任务,管理 Pod及Pod 中的容器。每个kubelet 进程会在 API Server 上注册节点自身信息,定期…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...