首页 > 代码库 > 函数模板
函数模板
--------------------siwuxie095
函数模板
这里介绍 函数模板,那么为什么要用函数模板呢?
看如下实例:
当要写一个比较大小的函数并返回较大的值时:
1)如果要比较两个 int 类型的值,就写成第一个函数的形式
2)如果要比较两个 float 类型的值,就写成第二个函数的形式
3)如果要比较两个 char 类型的值,就写成第三个函数的形式
三个函数除了数据类型有所不同之外,它们的运算逻辑是完全相同的,
在这种情况下,如果我们要写上这三个函数,简直是太痛苦了,而且
做的工作也没有意义和价值
最好是能够有一种方案,即 将类型作为参数传递进去,通过计算机
自动生成这三个函数,分别处理 int 类型、float 类型、char 类型的
数据,并能根据传入的数据类型做相应的处理,取得相应的返回值
如果想这么做,我们需要三个关键字:template、typename、class
其中:
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】
函数模板