函数模板(初阶)

       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;
}

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/425440.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自制一键杀死端口进程程序# tomcat 如何杀死tomcat进程

直接cmd 窗口执行如下命令即可 netstat -ano | findstr :8080 taskkill /F /PID <PID>简简单单的两个指令,总是记不住,也懒的记, 每次端口冲突的时候, 都是直接查百度,很苦逼, 如果有一个程序,直接输入端口号,点击按钮直接杀死进程,岂不爽歪歪. 跟我一起制作一个屠猫的…

【D3.js in Action 3 精译_022】3.2 使用 D3 完成数据准备工作

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可视化最佳实践&#xff08;下&#xff09;1.4 本章小结 第二章…

【网络原理】❤️Tcp 常用机制❤️ —— 延时应答,捎带应答, 面向字节流, 异常情况处理。保姆式详解 , 建议收藏 !!!

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

[数据集][目标检测]无人机识别检测数据集VOC+YOLO格式6986张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6986 标注数量(xml文件个数)&#xff1a;6986 标注数量(txt文件个数)&#xff1a;6986 标注…

‌内网穿透技术‌总结

内网穿透是一种网络技术&#xff0c;通过它可以使外部网络用户访问内部网络中的设备和服务。一般情况下&#xff0c;内网是无法直接访问的&#xff0c;因为它位于一个封闭的局域网中&#xff0c;无法从外部访问。而通过内网穿透&#xff0c;可以将内部网络中的设备和服务暴露在…

数据稀缺条件下的时间序列微分:符号回归(Symbolic Regression)方法介绍与Python示例

时间序列概况在日常生活和专业研究中都很常见。简而言之,时间序列概况是一系列连续的数据点 y(0), y(1), …, y(t) ,其中时间 t 的点依赖于时间 t-1 的前一个点(或更早的时间点)。 在许多应用中,研究者致力于预测时间序列概况的未来行为。存在各种建模方法。这些模型通常基于过…

Unity让摄像机跟随物体的方法(不借助父子关系)

在Unity中&#xff0c;不使用子对象的方式让相机跟随物体移动&#xff0c;我们通过编写脚本来实现。下面放一个从工程中摘出来的的C#脚本示例&#xff0c;用于将相机绑定到一个Target对象上并跟随其移动&#xff1a; using UnityEngine; public class FollowCamera : MonoBeh…

DPDK基础入门(十):虚拟化

I/O虚拟化 全虚拟化&#xff1a;宿主机截获客户机对I/O设备的访问请求&#xff0c;然后通过软件模拟真实的硬件。这种方式对客户机而言非常透明&#xff0c;无需考虑底层硬件的情况&#xff0c;不需要修改操作系统。 半虚拟化&#xff1a;通过前端驱动/后端驱动模拟实现I/O虚拟…

【STM32】CAN总线基础入门

CAN总线基础入门 一、CAN简介二、主流通信协议对比三、CAN物理层1、CAN硬件电路2、CAN电平标准3、CAN收发器 – TJA1050&#xff08;高速CAN&#xff09;4、CAN物理层特性 四、帧格式1、CAN总线帧格式2、数据帧&#xff13;、数据帧各部分用途简介&#xff14;、数据帧的发展历…

大模型参数高效微调技术原理综述(八)-MAM Adapter、UniPELT

MAM Adapter 背景 近年来提出了多种参数高效的迁移学习方法&#xff0c;这些方法仅微调少量&#xff08;额外&#xff09;参数即可获得强大的性能。虽然有效&#xff0c;但人们对为什么有效的关键要素以及各种高效微调方法之间的联系知之甚少。 下图展示了不同的微调方法&am…

小米,B站网络安全岗位笔试题目+答案

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

坚持的力量--完成向CSDN迁移500篇技术文章阶段小记-以此自勉

前言&#xff1a;本文为迁移前的博客中的文章《坚持的力量-写给第1000篇文章笔记》发表于 publish:May 14, 2021 -Friday&#xff0c;作为原个人博客中累计写满1000篇文章的总结和鼓励。因在向CSDN迁移文章的过程中进行了一些文章合并等调整&#xff0c;总文数大量下降&#xf…

ACM模式下算法题输入输出攻略【C++】

文章目录 [TOC] 1. 核心代码模式与ACM模式1.1 ACM模式介绍1.2 注意事项 2. C常用的输入输出方法2.1 输入2.1.1 cin注意事项2.1.2 getline()注意事项2.1.3 getchar()注意事项 2.2 输出 3. 案例3.1 一维数组输入3.1.1 固定长度的一维数组3.1.2 不固定长度的一维数组 3.2 二维数组…

使用ddns-go实现自动配置IPv6的DDNS

正文共&#xff1a;888 字 17 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面说到通过PPPoE拨号获取到的IPv6地址没有发生变化&#xff08;企业路由器配置IPv6家用宽带的PPPoE拨号示例&#xff09;&#xff0c;结果说完就打脸了。中间家里停了一次电&#xff0c;路由器重新…

Transformer模型详细步骤

Transformer模型是nlp任务中不能绕开的学习任务&#xff0c;我将从数据开始&#xff0c;每一步骤都列举出来&#xff0c;然后对应重点的代码进行讲解 ------------------------------------------------------------------------------------------------------------- Trans…

物品识别——基于python语言

目录 1.物品识别 2.模型介绍 3.文件框架 4.代码示例 4.1 camera.py 4.2 interaction.py 4.3 object_detection.py 4.4 main.py 4.5 运行结果 5.总结 1.物品识别 该项目使用Python&#xff0c;OpenCV进行图像捕捉&#xff0c;进行物品识别。我们将使用YOLO&#xff08…

re题(23)BUUFCTF-[FlareOn4]login

BUUCTF在线评测 (buuoj.cn) 下载后打开看到是一个txt和一个html 分别打开看看&#xff0c;txt是提示&#xff0c;html应该就是要破解的网页 打开网页&#xff0c;查看源代码 找到程序&#xff0c;变灰的部分是关键&#xff0c;是指如果是前13个字母就加13&#xff0c;如果是…

小程序开发设计-第一个小程序:注册小程序开发账号②

上一篇文章导航&#xff1a; 小程序开发设计-小程序简介①-CSDN博客https://blog.csdn.net/qq_60872637/article/details/142217803?sharetypeblogdetail&sharerId142217803&sharereferPC&sharesourceqq_60872637&spm1011.2480.3001.8118 须知&#xff1a;不…

C++设计模式——Prototype Pattern原型模式

一&#xff0c;原型模式的定义 原型模式是一种创建型设计模式&#xff0c;它允许通过克隆已有对象来创建新对象&#xff0c;从而无需调用显式的实例化过程。 原型模式的设计&#xff0c;使得它可以创建一个与原型对象相同或类似的新对象&#xff0c;同时又可以减少对象实例化…

Rust Windows下编译 静态链接VCRuntime140.dll

Rust 编译出来的exe默认动态链接VC运行库&#xff0c;分发电脑上需要安装有Microsoft Visual C Redistributable for Visual Studio 2015运行库。 编译时能静态链接进去&#xff0c;就省去客户端未安装运行库的问题。方法如下: 只需在当前根目录下新建.cargo\config.toml&#…