当前位置: 首页 > news >正文

函数模板(初阶)

       Hello,大家好,我们大家都知道,C++这个编程语言是由C语言继承而来的,因为是继承,所以我们的C++就要做出一些区分,要不然的话,就和C语言没有本质上的区别了,我们现在在社会中使用比较多的是C++而非是C语言,是因为这里我们C++的祖师爷在C语言的基础之上又设计了一个模板相关的内容,这个模板就受到了很多人的欢迎。

目录

1.前情提要

2.泛型编程

3.函数模板

    3.1函数模板的概念

    3.2函数模板的格式

    3.3函数模板的原理

    3.4函数模板的实例化

    3.5模板参数的匹配原则

4.类模板

    4.1类模板的格式

    4.2类模板的实例化


1.前情提要

       我们在C语言中经常会使用到一些相同的函数,就比如说Swap函数,我们在前面的C语言编程中就经常会使用到这个Swap函数来交换两个同类型的数据,我们要交换的数据的类型往往不止一种,我们要交换两个int类型的数据,double类型的数据等等,我们要为每一个类型的数据交换都要写一个Swap交换函数,这样就很费时间和空间,这些函数明明达到的效果都是一样的,但是却要写好多的一模一样的函数,很不爽,我们C++的祖师爷考虑到了这种情况,于是,就发明了模板这个东西来改变这种情况。

2.泛型编程

       编写于类型无关的通用代码,是代码复用的一种手段,模板是泛型编程的一种基础。模板又分为函数模板和类模板。

3.函数模板

    3.1函数模板的概念

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

    3.2函数模板的格式

template<class T>; 

       class T 就是参数列表的类型,编译器会根据类型来生成对应的函数,为了避免不必要的麻烦,因此这里建议参数列表中有几个形参,这里就写几个:

template<class T1,class T2......>

       比如:在这里写一个Swap交换函数。

#include<iostream>
using namespace std;
template<typename T>
void Swap(T a1, T a2)
{T tmp=a1;a1 = a2;a2 = a1;
}
int main()
{int a = 11, b = 22;Swap(a, b);//这里我们调用Swap函数的时候,那个Swap模板中的T就被编译器自动识别为int,编译器会自动构造一个int类型的Swap函数。cout << a << " " << b << endl;//11 22double c = 1.1, d = 2.2;Swap(c, d);//当我们传double类型的数据过去的时候,这个Swap函数中的T就会被编译器自动识别为double,编译器会自动构造一个double类型的Swap交换函数。cout << c << " " << d << endl;//1.1 2.2char e = 'e', f = 'z';Swap(e, f);//当我们传char类型的数据过去的时候,这个Swap函数中的T就会被编译器识别为char,编译器会自动构造一个cahr类型的Swap交换函数。cout << e << " " << f << endl;//z ereturn 0;
}

注:typename是用来定义模板参数的关键字,我们这里再定义模板参数的时候,其实不仅仅能使用typename这一个关键字,我们还可以使用class这个关键字来代替上述代码中的typename关键字(class/typename这两个关键字的效果都是一样的,不管写谁都可以)。切记:这里不可以使用struct来代替class。

template<class T1,class T2>

    3.3函数模板的原理

       函数模板类似于就是一个蓝图一样,是编译器的使用方式产生特定具体类型函数的摸具。总结下来就是将原本应该有我们做的重复的事情交给了编译器去做。

template<typename T1,typename T2>
void swap(T1& x,T2& y)
{   }

       在编译器的编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演并生成对应类型的函数,以供我们去使用,就比如说,当int类型处理上述的函数时,编译器会通过对实参类型的推演将T1,T2确定为是int类型,然后产生一份专门处理int类型的代码,任何类型均是如此。

    3.4函数模板的实例化

       用函数模板生成对应的函数这个过程成为是模板的实例化。

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

#include<istream>
using namespace std;
template<class T>//这里我们传过来的参数有几种类型,我们在这里就定义几个class/typename。
T add(T& a1, T& a2)
{return a1 + a2;
}
template<class T1,class T2>//这里我们传过来的参数有几种类型,我们在这里就定义几个class/typename。
void Add(T1& b1, T2& b2)
{int a = b1 + b2;
}
int main()
{int a1 = 1, a2 = 2;add(a1,a2);//编译器会自动根据出过去的实参(也就是a1和a2的类型)确定出T为int。double b1 = 1.1, b2 = 2.2;add(b1, b2);//编译器会自动根据出过去的实参(也就是b1和b2的类型)确定出T为double。Add(a1,b2);//编译器会自动根据出过去的实参(也就是a1和b2的类型)确定出T1为int类型,确定出T2为double类型。return 0;
}

注意:这里我们传过来的参数有几种类型,我们在这里就定义几个class/typename,如果我们传过去的参数类型有两种的话,但是我们定义的class/typename只有一种的话,那么,这样的话,编译器就无法分清这里定义的这个T是哪一个类型,就会出现编译报错的问题。

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

#include<istream>
using namespace std;
template<class T1,class T2>//这里我们传过来的参数有几种类型,我们在这里就定义几个class/typename。
void Add(T1& b1, T2& b2)
{  }
int main()
{int a1 = 1, a2 = 2;Add<int, int>(a1, a2);//T1是int类型,T2也是int类型。double b1 = 1.1, b2 = 2.2;Add<double, double>(b1, b2);//T1是double类型,T2也是double类型。Add<int, double>(a1, b2);//T1是int类型,T2是double类型。return 0;
}

注意:1>.这个显示实例化的知识我们必须要掌握,这个知识点我们在后面会大量使用。

           2>.如果类型不匹配的话,那么编译器就会尝试着进行类型转换的操作,如果这个类型转换无法成功的话,编译器就会进行报错的操作。

    3.5模板参数的匹配原则

       (1).一个非模板函数可以和一个同名的函数木模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。

       (2).对于非模板函数和同名函数模板,如果其他的条件都相同的话,那在调用时会优先调用非模板函数,而不会从该模板中产生一个实例。如果模板可以产生一个具有更好匹配的函数,那么就会选择模板(换句话说,就是有现成的就用现成的,而不会自己创造一个)。

       (3).模板函数不允许自动类型转换,但普遍函数却可以进行自动类型转换。

4.类模板

    4.1类模板的格式

template<typename T1,typename T2>
class date//date是类模板名
{//类内成员变量
};

    4.2类模板的实例化

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

#include<iostream>
using namespace std;
template<typename T>
class date//定义了一个类类型的模板
{
public://我们在模板里面实现一个Add函数T Add(T& a1,T& a2){   }void Swap(T& b1, T& b2);
};
//接下来,我们来写一下Swap函数的定义,在写之前这里还必须要补充一个知识点,就是每一个模板的作用域它仅限于当前的这个类,除了这个类之后就不管了,因此,对于类外的函数来说,我们就必须还得重新再写一个模板。
template<typename T>
void date<T>::Swap(T& b1, T& b2)
{   }
int main()
{date<int> d;//类型名/类型:date<int>   //(date<int>即是类型名,同时也是类型)return 0;
}

注意:类模板都是显示实例化。

       今天我们关于初阶函数模板的知识就先讲到这里了,谢谢大家的支持,你们的支持就是我坚持的巨大动力。

相关文章:

函数模板(初阶)

Hello&#xff0c;大家好&#xff0c;我们大家都知道&#xff0c;C这个编程语言是由C语言继承而来的&#xff0c;因为是继承&#xff0c;所以我们的C就要做出一些区分&#xff0c;要不然的话&#xff0c;就和C语言没有本质上的区别了&#xff0c;我们现在在社会中使用比较多的是…...

中间件之RocketMQ

RocketMQ是一个开源的分布式消息队列系统&#xff0c;起源于阿里巴巴集团内部。最初&#xff0c;RocketMQ&#xff08;前身为Metaq&#xff09;被设计为满足阿里巴巴集团内部大规模分布式系统下的高吞吐量、低延迟和高可靠性的消息传递需求。随着其在阿里巴巴内部的广泛应用和不…...

linux第二课(docker的安装使用)

目录 一.关于docker (1)背景引入 (2)docker介绍 (3)功能 (4)Docker架构 二.docker的安装及相关的命令 (1)docker的安装 (2)docker的配置 (3)docker镜像命令 (4)容器命令 三.docker安装myaql ​编辑 四.数据卷挂载 1.数据卷挂载引入 2.数据卷挂载图解 3.数据卷的安装…...

Java数据存储结构——二叉查找树

文章目录 22.1.2二叉查找树22.1.2.1 概述22.1.2.1二叉查找树添加节点22.1.2.2二叉查找树查找节点22.1.2.3 二叉树遍历22.1.2.4 二叉查找树的弊端 22.1.2二叉查找树 22.1.2.1 概述 二叉查找树,又称二叉排序树或者二叉搜索树 二叉查找树的特点&#xff1a; 每一个节点上最多有…...

JavaScript 事件处理

一、简介 ​ 事件&#xff1a;发生在HTML元素上的事情&#xff0c;可以是用户的行为&#xff0c;也可以是浏览器的行为&#xff0c;如 用户点击了某个HTML元素用户将鼠标移动到某个HTML元素上用户输入数据时光标离开页面加载完成 ​ 事件源&#xff1a;事件触发的源头&#xf…...

容器技术--Docker应用部署

应用部署 容器部署mysql 搜索并拉取镜像;基于镜像启动容器,注意端口映射、目录映射启动后即可连接# 搜索镜像 docker search mysql # 拉取镜像 docker pull mysql:5.7 # docker pull mysql 默认拉取最新的# 创建mysql容器, -p端口映射(宿主端口:容器端口) -e 环境变量,镜…...

医院管理|基于java的医院管理系统小程序(源码+数据库+文档)

医院管理系统小程序 目录 基于java的医院管理系统小程序 一、前言 二、系统设计 三、系统功能设计 医生信息管理 排班信息管理 科室信息管理 科室预约 病历信息 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a;…...

golang学习笔记21——golang协程管理及sync.WaitGroup的使用

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang应用级os框架使用案例&#xff0c;欢迎star案例&#xff1a;基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识&#xff0c;这里有免费的golang学习笔…...

C++初阶大全

目录 一.命名空间 1.命名空间定义 2.命名空间使用 二.C输入&输出 三.缺省参数 四. 函数重载 五.引用 1.常引用 2.传值、传引用效率比较 3.引用和指针的区别 4.引用和指针的不同点: 小知识点: 六.内联函数 七.auto关键字(C11) 1.auto的使用细则 八.基于范围…...

使用Redis实现用户关注博客的推模式

目录 一、思路 二、实现代码&#xff1a; 一、思路 发布者&#xff1a; 这里采用redis的zset结构&#xff0c;将键设置为被推送用户id&#xff0c;值设置为博客id&#xff0c;score设置为时间戳 推送之前先查到当前发布博客用户的粉丝有哪些&#xff0c;然后去循环挨个推送…...

python常用模块之time、datetime、randow(14)

文章目录 前言1、time模块1.1 导入模块1.2 使用方法1.2.1 时间戳1.2.2 程序休眠1.2.3 扩展&#xff1a;按某种格式显示当前时间1.2.4 结构化时间 2、datetime模块2.1 导入模块2.2 使用方法2.2.1 得到当前系统的时间2.2.2 拓展&#xff1a;编写一个时钟小程序 3、random模块3.1 …...

根据NVeloDocx Word模板引擎生成Word(六-结束)

前面几篇已经把E6开发平台配套的Word模版隐藏NVeloDocx的基础用法介绍了一遍&#xff0c;这些基础用法基本上可以完全覆盖实际业务的绝大部分需求。所以我们这一篇就介绍一些边边角角的内容&#xff0c;给本系列来一个首尾。 本篇的主要内容有&#xff1a; 1、汇总计算&#…...

Android架构组件:MVVM模式的实战应用与数据绑定技巧

目录 引言 一、MVVM模式概述 1.1 MVVM模式简介 1.2 MVVM模式的优势 二、MVVM模式的实现 2.1 项目环境配置 2.2 创建MVVM组件 2.2.1 创建数据模型 2.2.2 创建数据仓库 2.2.3 创建ViewModel 2.2.4 创建布局文件 2.2.5 创建RecyclerView适配器 2.3 在Activity中绑定V…...

调用系统的录音设备提示:line with format PCM_SIGNED 16000.0 Hz

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 16000.0 Hz, 8 bit, mono, 1 bytes/frame, not supported. 打开 设置->隐私->麦克风->允许应用访问你的麦克风 与 16000Hz没关系 与 16000Hz没关系 与 16000Hz没关系...

android BLE 蓝牙的连接(二)

下面是基于实际的项目得到的具体步骤及核心代码 1、权限问题 先判断手机是否满足android4.3以上版本&#xff0c;再判断手机是否开启蓝牙 主要涉及蓝牙权限和位置权限&#xff0c;注意不同android版本之间权限申请的差异&#xff0c;以及android权限动态申请和静态申请的区别 …...

改编pikachu的打靶经历(题目不全)

前言 题目很少&#xff0c;只做了一些。正常版本的&#xff0c;完整的pikachu可参考下面这个师傅写的 https://www.cnblogs.com/henry666/p/16947270.html xss &#xff08;get&#xff09;反射xss 先尝试 1 这里有长度限制&#xff0c;而且&#xff0c;我改了长度&#xf…...

Linux进阶 修改文件所有者

修改文件所属组群——chgrp 修改文件所属组群很简单-chgrp命令,就是change group的缩写(我们可以利用这些来记忆命令) 语法:chgrp 组群 文件名/目录 举例: [root@redhat ~]# groupadd groupa[root@redhat ~]# groupadd groupb[root@redhat ~]# useradd -g groupa zgz[r…...

第312题|二重积分求旋转体体积(二)|武忠祥老师每日一题

解题思路&#xff1a;先画出图像&#xff0c;再利用旋转体体积计算公式进行解题。 1. 旋转体体积计算公式&#xff1a; 2.点到直线计算公式&#xff1a; 有了上面两条知识储备之后我们开始计算。 第一步&#xff1a;先计算出点到直线的距离&#xff1a; ymx&#xff0c;y-mx…...

redis基本数据结构-set

文章目录 1. set的基本介绍1.1. set底层结构之hash表的简单介绍1.2. 常用命令 2. 常见的业务场景2.1. 标签系统2.2. 社交网络好友关系 1. set的基本介绍 参考链接&#xff1a;https://mp.weixin.qq.com/s/srkd73bS2n3mjIADLVg72A redis 的 set 数据结构是一个无序的集合&#…...

Android 应用安装-提交阶段

经过前面准备、浏览、协调这些步骤&#xff0c;马上要进入提交阶段了。所谓提交&#xff0c;就是把这些安装应用的相关信息和状态都放到系统中。对于已安装普通应用&#xff0c;它其实分为两个步骤&#xff0c;先卸载旧包&#xff0c;再安装新包。当然&#xff0c;如果是新安装…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

goreplay

1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具&#xff0c;可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长&#xff0c;测试它所需的工作量也会呈指数级增长。GoRepl…...

Java多线程实现之Runnable接口深度解析

Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...

Python第七周作业

Python第七周作业 文章目录 Python第七周作业 1.使用open以只读模式打开文件data.txt&#xff0c;并逐行打印内容 2.使用pathlib模块获取当前脚本的绝对路径&#xff0c;并创建logs目录&#xff08;若不存在&#xff09; 3.递归遍历目录data&#xff0c;输出所有.csv文件的路径…...

Springboot 高校报修与互助平台小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;高校报修与互助平台小程序被用户普遍使用&#xff0c;为…...

2025-06-01-Hive 技术及应用介绍

Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具&#xff0c;它为海量结构化数据提供类 SQL 的查询能力&#xf…...

Jmeter(四) - 如何在jmeter中创建网络测试计划

1.简介 如何创建基本的 测试计划来测试网站。您将创建五个用户&#xff0c;这些用户将请求发送到JMeter网站上的两个页面。另外&#xff0c;您将告诉用户两次运行测试。 因此&#xff0c;请求总数为&#xff08;5个用户&#xff09;x&#xff08;2个请求&#xff09;x&#xff…...

SAP学习笔记 - 开发24 - 前端Fiori开发 Filtering(过滤器),Sorting and Grouping(排序和分组)

上一章讲了SAP Fiori开发的表达式绑定&#xff0c;自定义格式化等内容。 SAP学习笔记 - 开发23 - 前端Fiori开发 Expression Binding&#xff08;表达式绑定&#xff09;&#xff0c;Custom Formatters&#xff08;自定义格式化&#xff09;-CSDN博客 本章继续讲SAP Fiori开发…...