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 }
View Code

输出结果如下为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 }
View Code

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 }
View Code

输出结果为:

1 2
2 5.9
View Code

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 }
View Code

模板#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 }
View Code

然后使用一下语句隐式实例化:

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 }
View Code

输出结果是: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对象obout
43     obout.disp();
44     return 0;
45 }
View Code

输出结果如下:

Inside:  3.5
Outside:Inside:  2
View Code

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;     //类模板的隐式实例化,创建对象ob
22      cout<<ob.ReturnNum()<<endl;
23 }
24 
25 int main()
26 {
27    disp<Stack,int,8>();
28    return 0;
29 }
View Code

输出结果为:8。

 

posted @ 2016-09-24 14:59  ZYVV  阅读(294)  评论(0编辑  收藏  举报