函数模板

--------------------siwuxie095

   

   

   

   

   

   

   

   

   

函数模板

   

   

这里介绍 函数模板,那么为什么要用函数模板呢?

   

   

   

   

看如下实例:

   

   

   

当要写一个比较大小的函数并返回较大的值时:

   

1)如果要比较两个 int 类型的值,就写成第一个函数的形式

2)如果要比较两个 float 类型的值,就写成第二个函数的形式

3)如果要比较两个 char 类型的值,就写成第三个函数的形式

   

   

三个函数除了数据类型有所不同之外,它们的运算逻辑是完全相同的,

在这种情况下,如果我们要写上这三个函数,简直是太痛苦了,而且

做的工作也没有意义和价值

   

   

   

最好是能够有一种方案,即 将类型作为参数传递进去,通过计算机

自动生成这三个函数,分别处理 int 类型、float 类型、char 类型的

数据,并能根据传入的数据类型做相应的处理,取得相应的返回值

   

   

   

   

如果想这么做,我们需要三个关键字:templatetypenameclass

   

其中:

   

template,即 模板;而 typename 和 class 所起的作用是相同的

   

注意:这里的 class 不是用来定义类的,而是用来表明数据类型的

   

   

   

通过 class 来定义一个函数的模板:

   

   

   

当要定义函数模板时,需要通过 template 关键字来声明一个

函数模板,通过 class 或 typename 关键字来声明一个参数,

该参数能表明一种数据类型

   

在写 max() 函数时,返回值写上 T,参数用 T 来作参数类型,

而内部的逻辑不变

   

如果未来要传入的是 int 类型的数据,计算机就会通过函数模板

实例化出一个模板函数,即 T 全部被 int 取代,就能处理 int 类

型的数据了。如果未来要传入的是 float 类型的数据,同理 …

   

   

   

在具体使用时:

   

   

   

当使用 max() 比较两个数据大小时,如果不指定数据类型 T,

计算机会根据自己的判断选择一种模板函数,选择之后就会

有自己的计算逻辑,如:int ival=max(100,99);,其中 100

和 99 都是 int 类型的,就会自动实例化一个 int 类型的模板

函数,然后对 100 99 进行处理,并将 100 返回出来,作

为返回值赋值给 ival

   

如果指定了数据类型,如:char cval=max<char>('A','B');

在函数名后面用一对尖括号括起来,其中写明数据类型,就

指定传入的参数一定要是这种数据类型的参数才可以,然后

将返回值返回回来

   

   

   

函数模板 是函数的模具,通过模子就能一个一个的生产出

所谓的函数,也就是 模板函数

   

在计算机中,如果仅仅写出了函数模板而没有使用它,计算机

是不会产生任何代码数据的,因为它也不知道要产生什么样的

代码数据

   

只有当使用函数模板时,计算机才知道具体要实例化出一个怎

样的模板函数,此时,才会产生真正的代码,参与逻辑的运行

   

   

   

   

通过 typename 来定义函数的模板:

   

   

   

swap() 是一个数据交换的函数,所使用的关键字除了 template 就是

typename,在使用上也没有什么不同,调用 swap(),这里指定的类

型是 int,即 T 全部被 int 取代,那么传入的参数也必须是 int 类型的,

才能够处理

   

   

   

   

   

   

变量作为模板参数

   

   

看如下实例:

   

   

   

通过 template 关键字声明一个函数模板,这时,所传入的不再是类型,

而是个变量,该变量在真正去使用时,才会将函数模板实例化成一个模

板函数,它才是一个确定的值。如果不使用该函数模板,仍然没有任何

代码产生

   

使用时,传入的就不再是一个类型,而是一个确定的值,如:display<10>();

此时这个值其实就是一个常数,只不过在函数模板中体现出来的,看上去像是

一个变量,真正编译出来就是一个常数

   

   

   

   

   

   

多参数函数模板

   

   

模板有时会变的很复杂,因为我们不能确定在日常应用中,只有

一个类型作为模板的参数,如果有多个参数该如何处理呢?

   

   

看如下实例:

   

   

当有多个参数时,需要用逗号隔开,两个 typename 都不能省略,

此时,T 和 C 都变成了函数模板的参数,在使用时,需要将 T 和

C 的类型都指定出来,如:display<int,string>(a,str);

   

   

   

typename 和 class 所起的作用是一样的,所以在使用时,可以

混用,如下:

   

   

   

   

还可以这样来混用:typename 来定义数据类型 T,另外一个则是

变量 size,在使用时就可以指定 T 的数据类型和 size 的值,如下:

   

   

   

   

   

   

   

函数模板与重载

   

   

函数模板看上去就已经是一个重载的关系了,因为:通过函数模板

可以拓出无数个模板函数,我们可以尽情的去想象它能拓出的数据

类型,这些模板函数之间就形成了一种重载

   

此外, 不同的函数模板所拓出的模板函数,也可能形成重载

   

看如下实例:

   

 

   

当前这三个函数模板,其实都有所不同,第一个函数模板只有 1 个参数,

第二个函数模板有两个参数,这就是参数的个数不同。第三个函数模板

也只有一个参数,看上去和第一个函数模板是一样的,但是第三个函数

模板的模板参数本身就有两个

   

   

   

在使用时:

   

   

   

通过三个不同的函数模板可以实例化出三个不同的模板函数,它们

之间就形成了重载

   

注意:当定义出函数模板时,函数模板本身并不是互相重载的关系,

因为在内存中,仅仅是将函数模板定义出来,并不能在内存中产生

出任何代码

   

只有在使用时,编译器才会产生相应的函数代码,产生函数代码后,

这些函数代码彼此之间才称得上是重载关系

   

   

   

   

程序:

   

main.cpp:

   

#include "stdlib.h"

#include <iostream>

using namespace std;

   

   

//template关键字声明一个模板 T是模板类型 也是模板参数

template<typename T>

//此即为函数模板 如果仅仅只是写出函数模板 而没有使用它

//那么计算机是不会产生任何代码数据的 因为它也不知道要产生什么样的代码数据

void display(T a)

{

cout << a << endl;

}

   

//使用了不同的关键字 但意义一样(所起作用一样)可以混用

//推荐使用typename 毕竟class是类的关键字

template<typename T,class S>

void display(T t, S s)

{

cout << t << endl;

cout << s << endl;

}

   

   

//这里变量作为了模板参数 KSize 此时传入的既有类型参数 又有变量参数

template<typename T,int KSize>

void display(T t)

{

for (int i = 0; i < KSize;i++)

{

cout << t << endl;

}

}

int main(void)

{

//此即为模板函数:通过函数模板生产出来的函数 也即实例化

//这时计算机才会产生真正的代码 才会参与逻辑运行

display<char>('Q');

display<int, double>(5, 10.89);

display<int, 5>(9);

system("pause");

return 0;

}

   

//同一函数模板生产出来的模板函数互为重载

//不同函数模板生产出来的模板函数也有可能互为重载

//

//在定义出函数模板的时候 函数模板本身并不是互相重载的关系

//因为在内存当中我们仅仅将函数模板定义出来 并不能在内存中产生出任何的代码

//

//只有在使用它们的时候 编译器才会为我们产生出相应的函数代码来

//这些函数代码彼此间才称得上互为重载关系

   

   

   

   

   

   

   

   

   

【made by siwuxie095】

原文地址:https://www.cnblogs.com/siwuxie095/p/6817183.html