C++:函数模版简介

ops/2024/9/23 5:02:06/

       如果我们想要实现一个通用的交换函数,在C语言中,我们大概要定义无数个参数不同的交换函数,并且它们的函数名需要各不相同,相信这样的调用便会非常困难,想要调哪个函数还要记得对应的函数名。在C++中,有了重载的概念,这样我们可以相对方便的实现通用的交换函数,但是还是非常麻烦,但是今天的知识将会极大地改变这种情况。我们只需定义一个模板,编译器就会根据这个模板生成对应的函数。

一、函数模板

#include<iostream>
using namespace std;
//template<typename 变量名, typename 变量名, ......, typename 变量名>
template<typename T>
void Swap(T& a, T& b)
{T tmp = a;a = b;b = tmp;
}int main()
{//Date* p1 = new Date[10]{ {1,2,3}, {2,3,4} };float a = 4.6;float b = 3.9;Swap(a, b);int c = 7;int d = 8;Swap(c, d);cout << a << ' ' << b << endl;cout << c << ' ' << d << endl;return 0;
}

       这里的交换函数交换的是同类型的变量,模板只需接受一个参数。若有几个不同类型,那就定义几个不同的变量。

       调试程序,我们会发现不同的类型调用的交换函数貌似都是一个,但是实际上它们调的不是一同个函数。如下图所示:

       转到反汇编,我们可以看到两个swap调用的并不是同一个函数,它们各自的swap函数的地址不同。

       模板的作用只是按我们的需求帮我们实现足够数量的函数。它省去了我们实现大量不同参数类型的交换函数的步骤。

       其实,交换函数已经被纳入到库里面了,成为了一个库函数,我们需要的时候直接调用即可。它的函数名是swap。

       若一个函数中有多个参数,那这个时候怎么生成模板呢?

template<typename T>
T Add(T a, T b)
{return a + b;
}int main()
{//Date* p1 = new Date[10]{ {1,2,3}, {2,3,4} };int a = 1;float b = 2.3;cout << Add(a, b) << endl;return 0;
}

       若强制写成上面这段代码的形式,那么编译器会报错。我们可以显示实例化a和b,意思是,告诉编译器,a和b的类型是什么。因为生成模板函数之前会有一个推演的过程,推出来a和b的对象是什么类型的。如果类型有冲突那么就报错。我们显示实例化a和b,就是告诉编译器它们的类型是什么。

template<typename T>
T Add(T a, T b)
{return a + b;
}int main()
{//Date* p1 = new Date[10]{ {1,2,3}, {2,3,4} };int a = 1;float b = 2.3;//显示实例化 <>cout << Add<int>(a, b) << endl;return 0;
}

       上面这段代码的意思是将a和b都转换为int类型。其中b会进行隐式类型转换,不同类型进行类型转换会有可能丢失数据。

       那想要获得不同类型相加的返回值,我们可以使用auto做返回类型,就是让编译器自动推到返回的类型。

template<typename T1, typename T2>
auto Add(T1 a, T2 b)
{return a + b;
}int main()
{//Date* p1 = new Date[10]{ {1,2,3}, {2,3,4} };int a = 1;float b = 2.3;cout << Add<int>(a, b) << endl;return 0;
}

       模板函数和非模板函数可以同时存在,若调用的参数类型完全符合非模板函数,那么就会优先调用非模板函数,若调用参数类型不符合非木板函数,那么就会调用模板函数。


http://www.ppmy.cn/ops/44977.html

相关文章

寻找峰值 ---- 二分查找

题目链接 题目: 分析: 因为题目中要找的是任意一个峰值即可, 所以和<山脉数组的峰值索引>这道题差不多因为峰值左右都小于峰值, 所以具有"二段性", 可以使用二分查找算法如果nums[mid] < nums[mid 1], mid一定不是峰值, 所以left mid 1如果nums[mid] &…

香橙派华为昇腾CANN架构编译opencv4.9

香橙派华为升腾AI盒子 为啥要编译opencv4.9.0&#xff0c; 因为在4.9.0 中增加了华为昇腾CANN的外接开发库&#xff0c;下图为盒子外观&#xff0c;此次一接到这个盒子&#xff0c;立刻开始开箱操作&#xff0c;首先就是要编译opencv4.9&#xff0c;以前在香橙派3588 的盒子中…

如何让你的网站能通过域名访问

背景 当我们租一台云服务器&#xff0c;并在上面运行了一个Web服务&#xff0c;我们可以使用云服务器的公网IP地址进行访问&#xff0c;如下&#xff1a; 本文主要记录如何 实现让自己的网站可以通过域名访问。 买域名 可以登录腾讯云等主流公有云平台的&#xff0c;购买域名…

PHP身份证识别接口、线上平台如何实现身份证实名认证功能?

线上平台实现身份证实名认证的功能&#xff0c;需要结合身份证识别接口来完成。首先&#xff0c;用户通过上传身份证图片或者拍照的方式实现证件信息的提取&#xff0c;身份证实名认证接口通过对提取到的证件信息进行核验&#xff0c;以此来实现线上用户身份的实名认证&#xf…

go recover

recover 可以中止 panic 造成的程序崩溃。它是一个只能在 defer 中发挥作用的函数&#xff0c;在其他作用域中调用不会发挥作用。 // A _panic holds information about an active panic. // // A _panic value must only ever live on the stack. // // The argp and link fi…

滑动窗口模板(Java)

题目描述 有一个长为 &#x1d45b; 的序列 &#x1d44e;&#xff0c;以及一个大小为 &#x1d458; 的窗口。现在这个从左边开始向右滑动&#xff0c;每次滑动一个单位&#xff0c;求出每次滑动后窗口中的最大值和最小值。 例如&#xff0c;对于序列 [1,3,−1,−3,5,3,6,7] …

C# 元组 Tuple

C# 元组 Tuple 元组创建元组访问元组元素命名元组元素元组的类型使用元组作为方法返回值 解构解构元组的基本用法解构部分元组解构方法 元组 在C#中&#xff0c;元组&#xff08;Tuple&#xff09;是一种数据结构&#xff0c;它允许你将多个值组合成一个单一的对象。 元组在处…

【笔记】软件架构师要点记录(2)

【笔记】软件架构师要点记录 20240523案例一案例二案例三案例四案例五案例六案例七案例十 20240523 基于前10个架构案例场景&#xff0c;对用到的专业术语进行整理&#xff0c;方便后续查看。 案例一 MVC架构风格组件交互方式 MVC是一种用来构建用户界面时采用的架构设计风格…