当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++基础入门教程

C++primer里的template的用法

    --  template 的用法
    在程序设计当中经常会出现使用同种数据结构的不同实例的情况。例如:在一个程序中
    可以使用多个队列、树、图等结构来组织数据。同种结构的不同实例,也许只在数据元素
    的类型或数量上略有差异,如果对每个实例都重新定义,则非常麻烦且容易出错。那么能
    否对同种类型数据结构仅定义一次呢?答案是肯定的,C++提供的类模板(Class Template
    )就可以实现该功能。
    一、类模板
    类模板是C++提供的一种特殊机制,通过它我们可以定义一种特殊的类(称为模板类),在类
    的定义中可以包含待定的类型参数,在声明类的实例时,系统会自动根据传递的类型生成
    用户想要生成的类实例。下面是用C++实现的一个简单的模板类Clist的定义。
    Template <class T, int I> class CList
    {
    public:
    int SetItem(int Index, const T &Item);
    int GetItem(int Index, T &Item);
    private:
    T Buffer;
    }
    在这里,T是类型参数,I是整型常量参数。T和I的实际值是在声明具体类实例时指定的。
    模板类的<>号内可以包括任意个类型参数和常量参数(至少要有一个参数)。类型参数和
    常量参数可以是任何合法的标准类型和用户自定义类型,包括简单类型及各种结构体。同
    其他类一样,类成员函数SetItem的实现可以在类定义内完成,也可以在类CList定义处实
    现:
    template<class T, int I> int CList<T, I>::SetItem(int Index, const T &Item)
    {
    if ( (Index<0)||(Index>I-1) )
     return 0; // 出错
    Buffer[Index]= Item ;
     return 1; // 成功
    }
    值得注意的是,在类定义外完成函数实现时,必须以关键字template和类模板定义中相同
    的参数表(<>号内的)开头(上例为template<class T, int I>),并且范围分解操作符前的
    类名后应跟上模板参数名清单(上例为CList<T, I>)。另外,与非模板类不同的是,必须将
    函数实现包括在调用它的每个源文件中,使编译器能从函数实现产生代码。通常的做法是
    将模板类的函数实现也放在定义该类的头文件中,这样只需在调用的源文件中包含该头文
    件即可。
    那么,如何使用生成特定的类实例呢?我们可以像使用其他类一样来使用模板类,不过必须
    指定模板参数的值。例如采用如下声明:
    CList <int, 100> IntList;
    则使IntList成为CList类的实例,每次出现的T参数都换成int, 每次出现的I参数都换成
    100。这样,IntList类中的Buffer就是一个长度为100的整型数组,SetItem和GetItem函数
    参数是int值的引用。例:
    IntList.SetItem(0, 5); //给数组第一个元素赋为整数5
    模板类还可以像其他类一样可以定义构造函数和析构函数。下面我们以一种简单的数据
    结构——堆栈为例,来说明如何用类模板来构造通用数据结构。
    二、 利用类模板实现通用堆栈结构
    任何抽象数据结构在计算机中的实现,归根结底都只有两种方式:顺序存储(用数组实现)
    ,链式存储(用指针实现)。堆栈也不例外,按其实现方式可分为顺序栈(用数组实现)和链
    栈(用指针实现)。
    1. 通用顺序栈的实现
    因为顺序栈中的元素在空间上连续存储,栈顶的元素位置需要注明,所以构造顺序栈的模
    板类应该有这样的一些成员变量:一个待定类型和长度的数组Buffer,一个记录栈顶元素
    的数组下标的整型变量top。堆栈的基本操作主要有:入栈(Push)、出栈(Pop)、置空(Se
    tEmpty)、判断当前状态(IsEmpty)等,它们应用模板类的成员函数来实现。作为一个标准
    的类,它还应该有自己的构造函数和析构函数。具有这些功能的模板类,就可以作为一个
    通用的顺序栈来使用了。该类的定义如下:
    template <class T,int SIZE> class CArrayStackTemp
    {
    public:
    CArrayStackTemp () //缺省构造函数,构造一个空堆栈
    {
    top= -1;
    };
    ~ CArrayStackTemp (){};//析构函数
     void SetEmpty (); //置空堆栈
     bool IsEmpty(); //判断堆栈是否为空
     bool Push(T element); //入栈
     bool Pop(T& element);//出栈
    private:
    T Buffer[SIZE];
     int top;
    };
    与堆栈的基本操作相对应的成员函数的实现如下:
    template <class T, int SIZE> void CArrayStackTemp<T, SIZE>:: SetEmpty ()
    {
    top= -1; //将栈顶指针赋 -1,并不实际清除数组元素
    }
    template <class T, int SIZE> bool CArrayStackTemp<T, SIZE>:: IsEmpty ()
    {
    return(top == -1);
    }
    template <class T, int SIZE> bool CArrayStackTemp<T, SIZE>:: Push (T element
    )
    {
    top++;
    if (top>SIZE-1)
    {
    top--;
    return false; //堆栈已满,不能执行入栈操作
    }
    Buffer[top]=element;
    return true;
    }
    template <class T, int SIZE> void CArrayStackTemp<T, SIZE>:: Pop (T& element
    )
    {
    if (IsEmpty())
     return false;
    element =Buffer[top];
    top--;
    return true;
    }
    根据实际需要,还可以扩充堆栈功能。例如:加入取栈顶元素、求堆栈长度等操作,其方法
    如上。
    2. 通用链栈的实现
    模板类中允许使用指针和定义自己的结构,这就为实现链式结构提供了保证。这里采用一
    个单链表来实现堆栈,栈顶指针指向链表的第一个结点,入栈和出栈均在链表的头进行。
    该模板类的定义如下:
    template <class T> class CLinkStackTemp
    {
 

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接