c++中的函数模版和类模版

由于使用模板可使程序员创建具备通用类型的函数库和类库。模板也是C++语言支持参数化多态性的工具。程序员

函数模板编程

  函数模板能以一样的程序代码对不一样类型的数据进行处理,其关键是将所处理的数据类型说明为参数,即类型参数化。数组

  定义函数模板的通常形式是:函数

  template <class 类型参数名1 ,class 类型参数名 2,…>
  函数返回值类型 函数名(形参表)
  {
    函数体
  }工具

说明:spa

 (1)这里的类型参数名就是表明形形色色数据类型的通用参数名,它能够表明基本数据类型,也能够表明类。指针

 (2)编写函数模板的方法是:code

step 1:定义一个普通的函数,数据类型采用具体的普通的数据类型,仍以打印数组为例,先定义一个打印整型数组的普通函数:对象

              void printArray(int *array,int count)编译

               {

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

                   cout<<array[i]<<" ";

                   cout <<endl;

     }

    step 2:将数据类型参数化:将其中具体的数据类型名(如 int )所有替换成由本身定义的抽象的类型参数名(如T)。

    step 3:在函数头前用关键字template引出对类型参数名的声明。这样就把一个具体的函数改形成一个通用的函数模板:
        template <class T> void printArray(T *array,int count)
        {
             for (int i=0;i<count;i++)
              cout<<array[i]<<" ";
        }

 (3)函数模板不是一个能够执行的函数,它只是对函数功能的程序描述,编译程序不为它生成执行代码。

 (4)当编译程序遇到函数调用:

 函数名 (实参表)时,自动将实参表中具体的数据类型替换函数模板中的类型参数,生成一个隐含的重载函数,该重载函数 的程序代码与函数模板相同,类型则采用实参表中的具体数据类型。仍之前面所建立的打印数组函数模板为例,当程序出现函数调用语句 printArray(a,aCount);时,编译程序将根据第一个实参a的数据类型int 匹配类型参数T,将函数模板中的全部T都替换成具体的数据 类型int,从而产生一个具体的可执行函数的定义(这个过程称为模板实例化):

 void printArray(int *array,int count);

模板函数

函数模板是对一组函数的描述,它不是一个实实在在的函数,编译系统并不产生任何执行代码。当编译系统在程序中发现有与函数模板中相匹配的函数调用时,便生成一个重载函数,该重载函的函数体与函数模板的函数体相同。该重载函数称为模板函数

 

类模板

类模板概念的由来:列举一个链表类来讨论类模板引进的必要性。下面有一个List类是链表类,嵌套了一个Node结构类型。具体定义以下:

class List
{      //定义链表类
public:
    List();       //声明构造函数
    void Add(int&);    //声明增长节点的成员函数
    void Remove(int&);  //声明删除节点的成员函数
    int* Find(int&);    //声明查找节点的成员函数
    void PrintList();   //声明打印链表的成员函数
    ~List();       //声明析构函数
protected:
    struct Node
    {    //定义结点的结构类型
        Node *pNext;   //指向下一个结点的指针成员
        int* pT;     //指向本结点数据的指针成员
    }
};

该链表结点的数据类型是int型,若是要使链表中结点的数据是其它类型(如char型、double型),就要从新定义链表类,因为这些类仅仅只是 结点的数据类型不一样,其他代码彻底相同,所以形成程序代码大量重复。为链表类家族建立一个通用链表类模板就能最大限度地减小程序代码的冗余,为此引进类模 板。将上述的List类中的数据类型用一个通用参数T来代替,以下所示:

 

template<class T>
class List
{      //定义通用链表类模板
public:
    List();       //声明构造函数
    void Add(T&);    //声明增长节点的成员函数
    void Remove(T&);  //声明删除节点的成员函数
    T* Find(T&);    //声明查找节点的成员函数
    void PrintList();   //声明打印链表的成员函数
    ~List();       //声明析构函数
protected:
    struct Node{    //定义结点的结构类型
        Node *pNext;   //指向下一个结点的指针成员
        T* pT;     //指向本结点数据的指针成员
    };
};

 

  这个类模板中使用了参数类型T,它被用在成员函数Add()、Remove()和Find()的说明中以及结构体的定义中。实际上,一个类模板是描述了一组类。可见,引进类模板也一样是为了减小程序员的重复劳动,克服程序冗余的一种方法。

  如同函数模板同样,使用类模板使用户能够为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型。 类模板是对一批仅仅成员数据类型不一样的类的抽象,程序员只要为这一批类所组成的整个类家族建立一个类模板,给出一套程序代码,就能够用来生成多种具体的 类,(这类能够看做是类模板的实例),从而大大提升编程的效率。

  定义类模板的通常形式是:

 

template <类型名 参数名1,类型名 参数名2,…>
class 类名
{
    类声明体
};
 
例如,
template <class T>
class Smemory
{
    …
  public:
  void mput(T x);
  …
}

 

  表示定义一个名为Smemory的类模板,其中带类型参数T。

  在类模板的外部定义类成员函数的通常形式是:

 

template <类型名 参数名1,类型名 参数名2,…>
函数返回值类型 类名<参数名 1 参数名 2,…>::成员函数名(形参表)
{
  函数体
}
例如:
template <class T>
void Smemory<T>::mput(T x)
{…}

 

  表示定义一个类模板Smemory的成员函数,函数名为mput,形参x的类型是T,函数无返回值。

  类模板是一个类家族的抽象,它只是对类的描述,编译程序不为类模板(包括成员函数定义)建立程序代码,可是经过对类模板的实例化能够生成一个具体的类以及该具体类的对象。

  与函数模板不一样的是:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定

其实例化的通常形式是:

  类名 <数据类型 1(或数据),数据类型 2(或数据)…> 对象名

例如,Smemory<int> mol;表示将类模板Smemory的类型参数T所有替换成int 型,从而建立一个具体的类,并生成该具体类的一个对象mol。

相关文章
相关标签/搜索