函数模板
来源:互联网 发布:手机淘宝商品的秒杀 编辑:程序博客网 时间:2024/06/06 01:17
1、模板
使用泛型来定义函数,其中的泛型可以用具体的数据类型(比如int或double)替换。通过将数据类型作为参数传递给模板,可使编译器生产该类型的函数。
1.1、为何需要函数模板
如果要交换两个int类型,则可以定义一个函数,如果要交换double类型,则可以定义另外一个函数,如果要交换float类型,则可以定义第三个函数,但是这样显得很复杂。
函数模板可以将数据类型作为参数
template <typename AnyType>void swap(AnyType &a,AnyType &b){ AnyType temp; temp = a; a = b; b = temp;}
1.2、实例
#include <iostream>template <typename T>void swap(T &a,T &b);int main(int argc , char** argv){ using namespace std; int i = 10 , j = 20; cout << "i = " << i << ",j = " << j << endl; cout << "Using compiler generated int swapper\n"; swap(i,j);//实际生成一个void swap(int &x,int &y); cout << "Now i = " << i << ",j = " << j << endl; double x =24.5 ,y = 30.2; cout << "x = " << x << ",y = " << y << endl; swap(x,y);//实际生成一个void swap(double &x,double &y); cout << "Now x = " << x << ",y = " << y << endl; return 0;}template <typename T>void swap(T &a, T &b){ T temp; temp = a; a = b; b = temp;}
1.3、模板使用原理
- 第一行template指出建立一个模板。关键字template和typename不可缺少。
- 模板不创建实际函数,只是告诉编译器如何定义函数,需要交换int的函数时,编译器将按照模板创建这样的函数,并用int代替AnyType。
- 函数模板并不减少可执行程序,可执行程序中不包含任何模板,模板只是给编译器看的,告诉编译器如何生产函数。
- 在可执行程序中,使用手动定义函数和使用模板都是一样的,但是对于程序员而言,减少了代码量,方便写代码。这也是最大的优点。
2、重载的模板
2.1、区分重载和函数模板的意义
函数模板:对不同的数据类型,要使用相同的算法,比如对于double和int的交换,都使用swap算法。
函数重载:要使用不同的算法,调用相同的函数名。
重载的模板:当多个数据类型使用同种算法时,可使用模板,但是并非所有数据类型都使用相同算法,这时必须重载,也就是重载模板。是模板和重载结合。调用相同的函数名,使用不同算法,处理不同数据类型。
2.2、模板,重载,重载模板三者实例
举例:
比如要交换int类型,或者double类型,就可以使用模板,定义函数swap,但是如果要交换一个int数组,那么交换int的算法则不能应用在交换数组上了,因此可以进行重载swap;但是数组可能是int,也可能是double,因此这时可以使用重载模板。
#include <iostream>template <typename T> //声明一个模板void swap(T &a , T &b);template <typename T> //声明一个重载模板,特征标不同void swap(T *a , T *b , int n);void show(int a[]);const int lim = 8;int main(int argc , char** argv){ using namespace std; int i = 10 , j = 20; cout << "i = " << i << ",j = " << j << endl; cout << "Using compiler generated int swapper\n"; //实际生成一个void swap(int &x,int &y); swap(i,j); cout << "Now i = " << i << ",j = " << j << endl; double x =24.5 ,y = 30.2; cout << "x = " << x << ",y = " << y << endl; //实际生成一个void swap(double &x,double &y); swap(x,y); cout << "Now x = " << x << ",y = " << y << endl; int d1[lim] = {0,4,6,3,2,6,8,1}; int d2[lim] = {6,3,8,5,2,6,8,1}; show(d1); show(d2); //匹配重载模板 swap(d1 , d2 , lim); show(d1); show(d2); return 0;}template <typename T>void swap(T &a, T &b){ T temp; temp = a; a = b; b = temp;}template <typename T>void swap(T a[] , T b[] , int n){ T temp; for(int i = 0; i < n ; i++){ temp = a[i]; a[i] = b[i]; b[i] = temp; }}void show(int a[]){ using namespace std; for(int i=0 ; i < sizeof(a) ; i++){ cout << a[i] << " "; } cout << endl;}
3、模板局限性
虽然使用模板就是为了针对不同的数据类型,但是某些特殊的类型,则可能无法处理。比如定义一个模板swap,可以处理int,double,float,但是不能处理数组,struct,等。
4、显示具体化
4.1、显示具体化的意义
要交换int或double类型,可以建立一个swap交换模板,但是如果类型是struct,则这种算法不适用。上面讲过使用重载模板,可以调用相同的函数名,使用不同的算法,但是重载模板必须是函数特征标不同,也就是函数参数个数不同。这对于swap的两个struct并不合适。
其实swap交换int和double,以及struct,参数个数都是2个,参数类型都是模板的typename T,因此不适合重载。而交换struct只不过是swap交换模板的一个特例。实现这个特例就用函数模板显示具体化。
4.2、第三代具体化
(1)对于一个同名的函数,可能最多有以下的几类函数:常规实现函数,模板显示具体化,模板函数,重载模板。
(2)显示具体化的原型和定义应以template <>开头,并通过名称指定类型。
(3)当实现了上述4类同名函数时,具体调用哪个函数,按照下面优先原则:常规函数 > 模板显示具体化 > 模板函数 。重载的模板因为参数个数不同,不同其他三个比较。
struct job{ char name[40]; double salary; int floor;};//常规实现函数void swap(job &a , job &b);//函数模板template <typename T>void swap(T &a , T &b>//模板显示具体化template <> void swap<job>(job &a , job &b);//模板重载template <typename T>void swap(T &a , T &b , int n);
4.3、显示具体化实例
#include <iostream>template <typename T>void swap(T &a , T &b);struct job{ char name[40]; double salary; int floor;};template <> void swap<job>(job &a , job &b);void show(job &x);int main(int argc , char** argv){ using namespace std; cout.precision(2); cout.setf(ios::fixed,ios::floatfield); int i = 10 , j = 20; cout << "i,j=" << i << "," << j << endl; cout << "Using comiler-generated int swapper" << endl; swap(i , j ); cout << "Now i,j=" << i << "," << j << endl; job sue = {"Su" , 7300.2 , 7}; job Mik = {"Mik" , 4566.3 , 6}; cout << "Before job swapping " << endl; show(sue); show(Mik); swap(sue , Mik); cout << "After job swapping \n" ; show(sue); show(Mik); ruturn 0;}template <typename T>void swap(T &a , T &b){ T temp; temp = a; a = b; b = temp;}template <> void swap<job>(job &x , job &y){ double t1; int t2; t1 = x.salary; x.salary = y.salary; t.salary = t1; t2 = x.floor ; x.floor = y.floor; y.floor = t2; }void show(job &x){ using namespace std; cout < x.name << ":" <<x.salary << "on floor" << x.floor << endl;}
- 函数模板、类模板
- 模板--->函数模板
- 模板函数,模板类
- 模板之函数模板
- C++ 模板->模板函数
- 类模板(函数模板)
- 模板---函数模板
- 函数模板 类模板
- 浅谈模板----函数模板
- 关于模板--模板函数
- 函数模板、类模板
- 模板之函数模板
- 模板函数
- 函数模板
- 函数模板
- 函数模板
- 函数模板
- 模板函数
- slf4j-api、slf4j-log4j12以及log4j之间什么关系?
- C++关于类的强制类型转换
- thinking in java学习之nio-bytebuffer4
- 英语需要更多的关心---2016年1月英语月总
- Java基础:运算符
- 函数模板
- cocos2d-x基础——cocos安装和使用基础
- Piotr's Ants
- 经典算法学习——直接选择排序
- 常用快捷键及shell基本命令
- 统计数字题解
- 离散化求RECT1
- 编译器的工作过程-节选自阮一峰的博文中并加以整理
- 图片缓存