当前位置: 首页 > 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;如果是新安装…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...