首页 > 代码库 > C++ 模板
C++ 模板
0.前言
模板是一种通用的描述机制,当使用模板时,允许使用通用类型来定义函数或类。通用类型可被具体类型(如int,double甚至是用户自定义类型)来代替。模板引入了一个全新的编程思维方式,称为“泛型编程”或者“通用编程”。
1.函数模板
1)函数模板声明形式如下:
template <class(或typename) A,...,int B (常数)>返回类型 函数名(参数列表){ //函数体}
class用于定义类,在模板引入c++后,最初定义模板的方法为:template<class T>,这里class关键字表明T是一个类型,后来为了避免class在这两个地方的使用可能给人带来混淆,所以引入了typename这个关键字,它的作用同class一样表明后面的符号为一个类型。
2)函数模板的使用
函数模板定义形式如下:
template <class T1[, class T2, ......]>函数原型;
3)函数模板实例化
3.1)隐式实例化:
1 /*************************main.c********************/ 2 #include <iostream.h> 3 using namespace std; 4 template<class Ex> 5 Ex Greater(Ex x,Ex y); 6 7 int main() 8 { 9 int inx=1;iny=2;10 cout<<Greater(inx,iny)<<endl; //实参为int类型,生产int型模板函数,并对第二个进行实参检查11 return 0;12 }13 14 template<class Ex>15 Ex Grearer(Ex x,Ex y)16 {17 return x>y?x:y;18 }
输出结果如下为2;
3.2)显示实例化标准格式如下:
template 返回类型 函数名<类型实参表> (函数参数表)
1 /*************************main.c********************/ 2 #include <iostream.h> 3 using namespace std; 4 template<class Ex> 5 Ex Greater(Ex x,Ex y); 6 7 template int Greater<int> (int,int); 8 9 int main()10 {11 int inx=1;iny=2;12 cout<<Greater(inx,iny)<<endl; //调用实例化模板函数13 return 0;14 }15 16 template<class Ex>17 Ex Grearer(Ex x,Ex y)18 {19 return x>y?x:y;20 }
3.3)利用特化可以解决某些类型在函数中的特殊操作,特化的基本格式如下:
template<> 返回类型 函数名[(类型实参表)](函数参数表)
其中类型实参表可以省略,有后续的函数参数表来指定。
1 /*************************main.c********************/ 2 #include <iostream.h> 3 using namespace std; 4 template<class Ex> 5 Ex Greater(Ex x,Ex y); 6 7 template<> double Greater<double>(double,double); //特化声明 8 9 int main()10 {11 int inx=1;iny=2;12 double dbx = 3.0,dby = 2.9;13 cout<<Greater(inx,iny)<<endl; //隐式实例化14 cout<<Greater(dbx,dby)<<endl; //优先调用特化函数15 return 0;16 }17 18 template<class Ex>19 Ex Grearer(Ex x,Ex y)20 {21 return x>y?x:y;22 }23 24 template<> double Greater(double x,double y) //特化定义25 {26 return x+y;27 }
输出结果为:
1 22 5.9
3.4)优先级和执行顺序
一般函数的执行顺序优先于模板的特化函数,模板的特化函数优先于实例化函数。
更特化的含义体现在“编译器做决定是执行的转换最少”,c++遵循部分排序规则来选择最优化模板函数。
1 template<class T> void f(T) {} #1 2 template<class T> void f(T*) {} #2 3 template<class T> void f(const T*) {} #3 4 template<class T> void g(T) {} #4 5 template<class T> void g(T&) {} #5 6 7 int main() 8 { 9 const int *p;10 f(p);11 int q;12 //g(q);13 }
模板#2比模板1更特化,模板3比模板2更特化,因此f(p)调用#3。然而模板#4和#5没有谁比谁更特化,因此g(q)会带来二义性错误。
2.类模板
1)类模板的定义
template<class 模板参数表>class 类名{ // 类定义};
2)类模板实例化
2.1)隐式实例化
首先定义类模板:
1 template <class T,int num> 2 class Stack 3 { 4 private: 5 T sz[num]; 6 int point; 7 public: 8 Stack(); 9 ...10 }11 12 template<class T,int num>13 Stack<T,num>::Stack()14 {15 point = 0;16 }
然后使用一下语句隐式实例化:
Stack<int,10> st;
下述语句不需要创建对象,编译器不会隐式生成类定义:
Stack<int,10> *ps;
2.2)显示实例化
template class 类名<类型参数表>
2.3)显示特化
template<> class 类名<特殊类型>{ 类定义;}
2.4)部分特化
template<class T1 , class T2> class Example{ //类定义};部分特化定义为:template<class T2> class Example<int ,T2>{ //类定义}
3)模板的嵌套
3.1)函数成员模板
成员模板不能声明为虚函数。
1 #include <iostream.h> 2 using namespace std; 3 template<class A> 4 class Test 5 { 6 public: 7 template<class B> 8 A f(B); 9 };10 11 template<class A>12 template<class B>13 A Test<A>::f(B)14 {15 return A(B);16 }17 18 int main()19 {20 Test<int> t;21 cout<<t.f(3.14)<<endl;22 return 0;23 }
输出结果是:3
3.2)对象成员模板
类模板的定义可以放在另一个类中,实例化后的模板对象可以作为另一个类的成员。
1 #include <iostream.h> 2 using namespace std; 3 template<class T> 4 class Outside 5 { 6 public: 7 template<class R> 8 class Inside 9 {10 private:11 R r;12 public:13 Inside(R r) //类模板的成员函数可以在定义时实现14 {15 r = x;16 }17 void disp();18 };19 void disp();20 private:21 Inside<T> t;22 } ;23 24 template<class T>25 template<class R>26 void Outside<T>::Inside<R>::disp() //类模板的成员函数也可以在定义外实现27 {28 cout<<"Inside: "<<Outside<T>::Inside<R>::r<<endl;29 }30 31 template<class T>32 void Outside<T>::disp()33 {34 cout<<"Outside:";35 t.disp();36 }37 38 int main()39 {40 Outside<int>::Inside<double> obin(3.5); //声明Inside类对象41 obin.disp();42 Outside<int> obout(2); //创建Outside对象obout43 obout.disp();44 return 0;45 }
输出结果如下:
Inside: 3.5Outside:Inside: 2
4)模板参数
模板可以作为另一个模板的参数类型,形式如下:
template<template <class T1> class T2,class T3,int Num>;
1 #include <iostream> 2 using namespace std; 3 4 template<class T,int num> 5 class Stack 6 { 7 private: 8 T sz[num]; 9 public:10 int ReturnNum(); 11 };12 template<class T1,int num1>13 int Stack(T1,num1>::ReturnNum()14 {15 return num1;16 }17 18 template<template<class Type,int NUM> class TypeClass,class T1,int N>19 void disp()20 {21 TypeClass<T1,N> ob; //类模板的隐式实例化,创建对象ob22 cout<<ob.ReturnNum()<<endl;23 }24 25 int main()26 {27 disp<Stack,int,8>();28 return 0;29 }
输出结果为:8。
C++ 模板