函数模板
来源:互联网 发布:接亲堵门游戏 知乎 编辑:程序博客网 时间:2024/06/06 07:52
1.函数模板
函数模板为通用函数的描叙。
(1)模板函数不能缩短可执行的程序,仍将使用独立的函数定义。但是模板函数更加简单可靠
(2)可以重载函数模板,和一般重载一样,要求函数特征标(参数表相异),且能够参数表包含非模板参数如int等
(3)模板属于编译时多态性,因为编译时自动根据模板生成模板函数。函数重载也是编译多态性。只有虚函数为运行多态。
2.显式具体化
即提供模板的函数的某些具体化版本,当编译器找到与函数调用匹配的具体化定义时,将使用该定义而不是模板。例如定义交换函数swap(),交换普通元素和结构体元素,但是要求结构体元素只要求交换部分数据域,如下:
struct job{ double salary; int rank;}template<tyname T>void swap(const T&,const T&);//通用版本template<> void swap<job>(const job&,const job& );//显式具体化版本template<tyname T>void swap(const T& a,const T& b)//通用版本{ T temp=a; a=b; b=temp;}template<> void swap<job>(const job& a,const job& b)//显式具体化版本,并不交换所有部分{ double temp=a.salary; a.salary=b.salary; b.salary=temp;}void main(){ int i=0,j=1; swap(i,j);//(i=1,j=0).......................job a={1000.00,1};job b={2000.00,2}swap(a,b);//(仅仅salary部分交换)......................}
3.编译器选择函数版本的规则
(1)完全匹配,但是匹配优先度:普通函数>显式具体化函数>模板函数
(2)提升转换匹配(char short转为int, long转为doubel)
(3)标准转换匹配(int 到 char, long 到double)
(4)用户自定义转换。即下文的显式实例化。
此时应注意,const与非const的区别只存在于指针和引用类型。也就是说,func(int),function(const int)具有相同的匹配等级。若func(int)被最优匹配,则后者也是最优匹配,此时会出现二义性。然后,对于最优匹配的参数表含有指针或者参数的情况,不会出现此种情况。
编译时,编译器倾向选择最具体且需要最少转换的函数。当然,也可以通过人为指定合适的调用,引导编译器。如:
template<tyname T>T less(const T& a,const T& b);//#1{ return a<b?:a,b;}int less(int a,int b)//#2{ return a<b?:a,b;}main(){ int i=0,j=1;double m=1.0,n=2.0;less(i,j);//#1less(m,n);//#2less<>(i,j);//#1,“<>”引导编译,要求使用模板函数匹配less<int>(m,n);//#1,显式实例化,m、n被强制转换}
4.非类型参数模板
只有运行时,细节才被真正的确定。但是在这里,处理的细节不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化。。非类型模板参数(Nontype Template Parameters)只能是整数类型, 指针, 引用。整型必须是常量表达式(constant expression), 指针和引用必须指向静态类型。
4.1类中的非参数类型模板
例如定义一个大小事先确定的stack类:
#include<stdexcept>#include<iostream>using namespace std;template<typename T, int MAXSIZE>class Stack{private: T elems[MAXSIZE]; int numElems;public: Stack(); void push(T const&); void pop(); T top() const; bool empty() const { return numElems == 0; } bool full() const { return numElems == MAXSIZE; }};template<typename T, int MAXSIZE>Stack<T, MAXSIZE>::Stack():numElems(0) {}template<typename T, int MAXSIZE>void Stack<T, MAXSIZE>::push(T const& elem){ if(numElems == MAXSIZE) { throw out_of_range("Stack<>::push(): stack is full"); } elems[numElems] = elem; ++numElems;}template<typename T, int MAXSIZE>void Stack<T, MAXSIZE>::pop(){ if(numElems <= 0) { throw out_of_range("Stack<>::pop(): stack is empty"); } --numElems;}template<typename T, int MAXSIZE>T Stack<T, MAXSIZE>::top() const{ if(numElems <= 0) { throw out_of_range("Stack<>::top(): stack is empty"); } return elems[numElems - 1];}
使用:
#include<iostream>#include<vector>#include<deque>#include<stdexcept>#include<string>#include<cstdlib>#include "stack4.h"using namespace std;int main(){ try { Stack<int, 20> int20Stack; Stack<int, 40> int40Stack; Stack<string, 40> stringStack; int20Stack.push(7); cout<<int20Stack.top()<<endl; int20Stack.pop(); stringStack.push("hello"); cout<<stringStack.top()<<endl; stringStack.pop(); stringStack.pop(); } catch(exception const& ex) { cerr<<"Exception: "<<ex.what()<<endl; //return EXIT_FAILURE; } cin.get(); return 0;}
4.2函数中的非类型参数模板
例如求数组大小模板函数:
template<unsigned int N,typename T> int coute(T (&a)[N]){ return sizeof(a)/sizeof(a[0]); }
4.3非类型参数模板函数的限制
(1)只能是int,指针或者引用,不能是float或者double,或者类对象之类。例如:
template<double VAT>double process(double v) //error{ return V * VAT;}template<string name> //errorclass MyClass { ...};
(2)使用全局指针作为模板参数,即extern类型的常量类型:
5.模板函数的使用要点
① 如果在全局域中声明了与模板参数同名的对象函数或类型,则被隐藏。在下面的例子中tmp 的类型不是double 是模板参数Type。
typedef double Type;template <class Type>Type min( Type a, Type b ){ // tmp 类型为模板参数 Type,不是全局 double Type tmp = a < b ? a : b; return tmp;}
② 在函数模板定义中声明的对象或类型,不能与模板参数同名。
template <class Type>Type min( Type a, Type b ){ typedef double Type; // 错误: 重新声明模板参数 Type Type tmp = a < b ? a : b; return tmp;}
③ 返回类型也可是模板类型参数
template <class T1, class T2, class T3>T1 min( T2, T3 );
④同一模板参数表必须使用不一样的参数名,但是相异的模板参数表可以使用相同的参数名
// 错误: 模板参数名 Type 的非法重复使用template <class Type, class Type>Type min( Type, Type ); //正确: 名字 Type 在不同模板之间重复使用template <class Type>Type min( Type, Type );template <class Type>Type max( Type, Type );
⑤函数模板也可以被声明为inline 或extern 应该把指示符放在模板参数表后面而不是在关键字template 前面。
template <typename Type> inlineType min( Type, Type );
- 函数模板、类模板
- 模板--->函数模板
- 模板函数,模板类
- 模板之函数模板
- C++ 模板->模板函数
- 类模板(函数模板)
- 模板---函数模板
- 函数模板 类模板
- 浅谈模板----函数模板
- 关于模板--模板函数
- 函数模板、类模板
- 模板之函数模板
- 模板函数
- 函数模板
- 函数模板
- 函数模板
- 函数模板
- 模板函数
- 单链表的逆置-C++实现
- 怎样才能看上去不那末白痴
- Android性能优化
- Sublime Text 2输入中文显示方框问号乱码
- 《iOS8 Swift编程指南》样书图片
- 函数模板
- window.location 对象
- Linux 串口编程
- Adobe Flash Player ActiveX 不能安装
- Search a 2D Matrix
- opencl入门介绍
- 1402 最大值
- 代码雨
- struct iphdr中的__LITTLE_ENDIAN_BITFIELD和__BIG_ENDIAN_BITFIELD