C++的模板

模板的具体实现 ―― 模板的实例化(instantiation)或具体化(specialization

 

1.函数模板

函数模板定义的一般格式为:

template < class 类型形参名1... class 类型形参名n >

    返回类型  函数模板名 ( 形参表 )  { 函数体 }

注意:

 

      1) 应在返回类型形参表函数体中使用上述的类型形参名

      2) 调用处则类似于一般函数,用户只需给出具体的实参。

      3) 模板函数调用时,不进行实参到形参类型的自动转换

 

1.1 函数模板例1:

定义一个函数模板max,而后对它进行不同的调用

 

#include <iostream.h> 

template <class T>

 T max (T a, T b)

{ 

    if(a>b)

                return a;

    else

                return b;

}

void main()

{

  int i1 = -11,  i2 = 0 ;

  double d1, d2;

  cout<<max(i1,i2)<<endl;

             //由实参i1i2,系统可确定类型形参T”对应于int

  cout<<max(23,-56)<<endl;

  cout<<max('f', 'k')<<endl;

  cin>>d1>>d2;

  cout<<max(d1,d2)<<endl;

        //cout<<"max(23,-5.6) = "<<max(23,-5.6)<<endl;

             //出错! 不进行实参到形参类型的自动转换,因为23和-5.6的类型不一致

}

程序执行后的显示结果如下:

int i1=-11, i2=0; => max(i1,i2) = 0

max(23,-56) = 23

char c1='T', c2='F'; => max(c1,c2) = T

max('f', 'k') = k

input double d1, d2 : 123.45 99.67

d1=123.45, d2=99.67 => max(d1,d2) = 123.45

 

1.2函数模板例2 -- 函数模板与函数重载 

      定义一个函数模板与一个函数,它们都叫做minC++允许这种函数模板与函数同名的所谓重载使用方法。但注意,在这种情况下,每当遇见函数调用时,C++编译器都将首先检查是否存在重载函数,若匹配成功则调用该函数,否则再去匹配函数模板

 

#include <iostream.h>

#include <string.h>

 

template <class type>

type min (type a, type b)

{

//type型的ab要能够进行“<”比较运算!

       return (a<b?a:b);

}

 

char* min (char* a, char* b)

{ 

//函数min,字符串型参数,不能直接使用“<”来进行比较

       return (strcmp(a,b)<0?a:b); 

}

 

void main()

{

     cout<<min(3,-10)<<endl;           //使用函数模板

     cout<<min(2.5,99.5)<<endl;

     cout<<min('m','c')<<endl;

     char* str1="The C program", * str2="The C++ program";

     cout<<min(str1, str2)<<endl;    //使用重载函数!

}

 

1.3 函数模板例3 -- 二函数模板重载

 

      定义两个函数模板,它们都叫做sum,都使用了一个类型参数Type,但两者的形参个数不同,C++允许使用这种函数模板重载的方法。

      注意,参数表中允许出现与类型形参Type无关的其它类型的参数,如“int size”

 

#include <iostream.h>

template <class Type>

 Type sum (Type * array, int size )

{

     //array数组前size个元素之和

    Type total=0;

    for (int i=0;i<size;i++)

         total+=*(array+i);

    return total;

}

template <class Type>

 Type sum (Type * a1, Type * a2, int size )

{

    //a1数组与a2数组前size个元素之和

    Type total=0;

    for (int i=0;i<size;i++)

         total+=a1[i]+a2[i];

    return total;

}

 

void main() {

    int a1[10],a2[8];

    float af[10];

    ...                                   //为数组分量定值

    cout<<sum(a1,10)<<endl;      //求出a1数组前10个元素之和并输出

    cout<<sum(af,10)<<endl;

    cout<<sum(a1,a2,8)<<endl;   //a1a2数组前8个元素之和并输出

}

 

 

2.类模板

2.1类模板的概念及其定义格式

利用类模板(带类型参数或普通参数的类),一次就可定义出具有共性的一组类。  即,可使得所定义类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值都可以是任意类型的。

 

类模板定义格式如下:

template < 类型形参或普通形参1的说明,... ,类型形参或普通形参n的说明 >

 class  类模板名

{

带上述类型形参或普通形参名的类定义体;

}

 

      说明类型形参时,使用“class 类型形参名”的方式,说明普通形参时,使用“<类型> 普通形参名”的方式。

  

注意:

1) 类定义体中应使用上述的“类型形参名”及“普通形参名”。

2) 利用类模板说明类对象时,要随类模板名同时给出对应于类型形参或普通形参的具体实参(从而实例化为一个具体的类)。

说明格式为:

              类模板名 < 形参1的相应实参,... ,形参n的相应实参  >

 注意:类型形参的相应实参类型名,而普通形参相应实参必须为一个常量  

 

3) 类模板的成员函数既可以在类体内进行说明(自动按内联函数处理),也可以在类体外进行说明。

    在类体外说明(定义)时使用如下格式:

       template < 形参1的说明,... ,形参n的说明 >

返回类型  类模板名 < 形参1的名字,... ,形参n的名字 >::函数名( 形参表 )

{

         ...   //函数体

}

 

    上述的形参1的名字来自于形参1的说明,由甩掉说明部分的类型而得,是对类型形参或普通形参的使用。而

  类模板名 < 形参1的名字,... ,形参n的名字 >::”所起的作用正是在类体外定义成员函数时在函数名前所加的类限定符!

 

例如,对具有一个类型参数T的类模板TestClass,在类体外定义其成员函数getData时的大致样式如下:

 

      template <class T>

      T  TestClass<T>::getData( 形参表 )

{

...      //函数体

};

 

      其中的TestClass<T>::所起的作用正是在类体外定义成员函数时在函数名前所加的类限定符!

 

2.2仅使用类型参数的类模板示例

#include <iostream.h>

template <class T>

class TestClass

{ 

  public:

     T buffer[10];  //T类型的数据成员buffer数组大小固定为10 (灵活性差!)   

     T getData(int j);  //获取T类型buffer(数组)的第j个分量

};

 

template <class T>     

T TestClass<T>::getData(int j)

{

    return *(buffer+j);  

};

 

void main()

{

TestClass<char> ClassInstA; //char取代T,从而实例化为一个具体的类

char cArr[6]="abcde"; 

 

for(int i=0; i<5; i++)

ClassInstA.buffer[i]=cArr[i];

 

for(i=0; i<5; i++)

 {

       char res=ClassInstA.getData(i);

       cout<<res<<"  ";

}

       cout<<endl;

 

TestClass<double> ClassInstF;  //实例化为另外一个具体的类

       double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};

 

       for(i=0; i<6; i++)

              ClassInstF.buffer[i]=fArr[i]-10;

 

       for(i=0; i<6; i++)

  {

              double res=ClassInstF.getData(i);

              cout<<res<<"  ";

         }

       cout<<endl;

}

程序执行后的显示结果如下:

a  b  c  d  e

2.1  13.2  24.3  35.4  46.5  57.6

 

2.3仅使用普通参数(非类型参数)的类模板示例

#include <iostream.h>

template <int i>

class TestClass

{

  public:

     int buffer[i]; 

              //使buffer的大小可变化,但其类型则固定为int(灵活性差!)     

     int getData(int j);  

};

 

template <int i>  

int TestClass<i>::getData(int j)

{

    return *(buffer+j); 

};

 

void main()

{

       TestClass<6> ClassInstF; 

       double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};

 

       for(i=0; i<6; i++)

             ClassInstF.buffer[i]=fArr[i]-10;

 

       for(i=0; i<6; i++)

 {

                double res=ClassInstF.getData(i);

                cout<<res<<"  ";

          }

       cout<<endl;

}

 

    程序执行后的显示结果如下:

2  13  24  35  46  57

 

 

 

 

 

2.4既使用类型参数又使用普通参数的类模板示例

#include <iostream.h>

#include "string.h"

template <class T, int i>

class TestClass

{

  public:

     T buffer[i];   //T类型的buffer,其大小随普通形参i的值变化(灵活性大!)

     T getData(int j); 

};

 

template <class T, int i> 

T TestClass<T,i>::getData(int j)

{

    return *(buffer+j);   

};

 

void main()

{

       TestClass<char, 5> ClassInstA;

       char cArr[6]="abcde";

 

       strcpy(ClassInstA.buffer, cArr);

 

       for(int i=0; i<5; i++)

{

           char res=ClassInstA.getData(i);

           cout<<res<<"  ";

          }

       cout<<endl;

 

TestClass<double, 6> ClassInstF;

       double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};

 

       for(i=0; i<6; i++)

           ClassInstF.buffer[i]=fArr[i]-10;

       for(i=0; i<6; i++)

{

               double res=ClassInstF.getData(i);

               cout<<res<<"  ";

          }

       cout<<endl;

}

     程序执行后的显示结果如下:

a  b  c  d  e

2.1  13.2  24.3  35.4  46.5  57.6

 

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值