通常有两种形式:函数模板和类模板;
一、函数模板通式
//template和class是关键字,class可以用typename 关键字代替,在这里typename 和class没区别
//<>括号中的参数叫模板形参
template <class 形参名,class 形参名,......>
返回类型 函数名(参数列表)
{
函数体
}
//实例
template <class T>
void swap(T& a, T& b){},
//调用-----函数模板的调用应使用实参推演来进行
int a=1;int b=2;
swap(a, b) //模板函数swap中的形参T就会被int 所代替,模板函数就变为swap(int &a, int &b)
double c=1.2;double d=2.4;
swap(c, d)//模板函数swap中的形参T就会被double 所代替,模板函数会被替换为swap(double &a, double &b)
二、类模板通式
template<class 形参名,class 形参名,…>
class 类名{ ... };
//实例
template<class T>
class A
{
public:
T a;
T b;
T hy(T c, T &d);
};
//调用-----对于类模板,模板形参的类型必须在类名后的尖括号中明确指定
A<int> m;//类A后面跟上一个<>尖括号并在里面填上相应的类型,类A中凡是用到模板形参的地方都会被int 所代替
A<int, double> m;//当类模板有两个模板形参时,类型之间用逗号隔开
//在类模板外部定义成员函数的方法
//当在类外面定义类的成员时template后面的模板形参应与要定义的类的模板形参一致。
template<模板形参列表> 函数返回类型 类名<模板形参名>::函数名(参数列表){函数体},
template<class T1,class T2> void A<T1,T2>::h(){}
代码实例
#include "stdafx.h"
#include <iostream>
using namespace std;
template <class T>
void sswap(T& a, T& b)//函数模板
{
T temper=a;
a=b;
b=temper;
cout<<a<<" "<<b<<endl;
}
template<class T> //类模板
class A
{
public:
T a;
T b;
T hy(T c, T &d);
};
template<class T>
T A<T>::hy(T c, T &d)//在类模板外部定义成员函数的方法
{
return c+d;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a=1,b=2;
cout<<a<<" "<<b<<endl;
sswap<int>(a,b);//类型可以根据a,b推导出来,<int>可以省略
double c=1.2,d=2.4;
cout<<c<<" "<<d<<endl;
sswap<double>(c,d);//类型可以根据c,d推导出来,<double>可以省略
A<int> m;//对于类模板,模板形参的类型必须在类名后的尖括号中明确指定
int e=3,f=4;
int g=m.hy(e,f);
cout<<e<<"+"<<f<<"="<<g<<endl;
getchar();
return 0;
}
三、模板的形参
有三种类型的模板形参:类型形参,非类型形参和模板形参
1、类型形参
类型形参由关键字class或typename后接说明符构成如
template<class T> void h(T a){};
其中T就是一个类型形参,
类型形参的名字由用户自已确定
2、非类型形参
非类型模板形参:模板的非类型形参也就是内置类型形参,如
template<class T, int a> class B{};
其中int a就是非类型的模板形参。
非类型模板的形参只能是整型,指针和引用
3、模板形参
略
四、类模板的默认模板类型形参
类模板的类型形参默认值形式为:
template<class T1, class T2=int> class A{};
为第二个模板类型形参T2提供int型的默认值。
类模板类型形参默认值和函数的默认参数一样,如果有多个类型形参则从第一个形参设定了默认值之后的所有模板形参都要设定默认值,
比如templateclass A{};就是错误的,因为T1给出了默认值,而T2没有设定。