C++泛型程序设计——类模板

8月 15th, 2012
Visited 4584 times, 1 so far today
0

Comments

                   对于类模板的声明形式与相应的函数模板相同,只需要在相应类之前加上关键字template<typename T> ,后面直接接相应的类的定义,唯一不同的地方就是类中所有的类型统一采用T来表式。当程序编译时来根据具体的类型来类模板特化(就是生成能处理具体类型的类)。类型模板T的作用及所处的位置总结:1.相应函数形参类型   2.函数返回值类型    3.局部变量类型。c++中所有的类模板定义在相应的头文件中。只要引入相应的头文件,即可应用相应的类模板。对于自定义的类模板,我们也要相应的全部定义到头文件中(即:不能像以前那样头文件.h和源文件.cpp分开来定义,即类名加::二元域作用符来定义在类外定义的函数。否则编译的时候会报找不到相应的外部引用错误。这个是模板类的独特之处)

例:1.类模板测试–Stack.h

#ifndef STACK_H
#define STACK_H

template <typename T>
class Stack{
public:
    Stack(int = 10);//构造函数默认值为10
    ~Stack(){//析构函数
        delete[] ptr;//析构相应的对象
    };
    bool isEmpty(){
        return top == -1;//即表示此堆栈是空的
    }
    bool isFull(){
        return top == size -1;//即表示堆栈已满
    }
    bool push(const T &);//压入相应的元素
    bool pop(T &);//弹出相应元素
private:
    int size;
    int top;
    T *ptr;//指向具体内存的指针
};

template <typename T>
Stack<T>::Stack( int i/*= 10*/ )//只能应用成员初始化列表器来初始化
    :top(-1),size(i>0?i:10),ptr(new T[size])//初始化列表器
{
    //empty
}

template <typename T>
bool Stack<T>::push( const T &pushValue )
{
    if(!isFull()){
        ptr[++top] = pushValue;//压入相应的元素
        return true;
    }
    return false;//这个地方就是为了用while时,放在条件里面来执行
}

template <typename T>
bool Stack<T>::pop( T &popValue)
{
    if(!isEmpty()){
        popValue = ptr[top–];
        return true;
    }
    return false;
}
#endif

//此处类的所有函数实现都在头文件中进行,避免编译时出错。错误原因上面已有说明

————————————————————————————————-

2.主要的main.cpp函数

#include <iostream>
#include “Stack.h”
#include <string>
using namespace std;

template<typename T> //模板函数来测试模板类
void testStack(Stack<T> &stack, T value, T incream, const string &stackName){
    cout<<“element start push into: “<<stackName<<endl;
    while(stack.push(value)){
        cout<<value<<”  “;
        value += incream;
    }
    cout<<“\nthe stack “<<stackName<<” is full, element:”<<value<<” is not push”<<endl;
    cout<<“\n\nelement start pop from: “<<stackName<<endl;
    while(stack.pop(value)){
        cout<<value<<”  “;
    }
    cout<<“\nthe stack “<<stackName<<“is empty!”<<endl;
}

int main(){
    //Stack<int> a(5);//创建一个对象,对象维护一个int类型的堆栈
    //int intValue = 1;
    //cout<<“IntStack is pushed:”<<endl;
    //while(a.push(intValue)){
    //    cout<<intValue<<” “;
    //    intValue += 1;//并不断的增加1
    //}
    //cout<<“\nIntStack is full,not push”<<endl;

    //cout<<“IntStack is pop!”<<endl;
    //int popValue = 0;
    //while(a.pop(popValue)){
    //    cout<<popValue<<” “;
    //}
    //cout<<“\nIntStack is empty!”<<endl;

    //cout<<endl<<endl<<endl;
    //Stack<double> b;//创建一个对象,对象维护一个int类型的堆栈
    //double doubleValue = 1.1;
    //cout<<“DoubleStack is pushed:”<<endl;
    //while(b.push(doubleValue)){
    //    cout<<doubleValue<<” “;
    //    doubleValue += 1.1;//并不断的增加1
    //}
    //cout<<“\nDoubleStack is full,not push”<<endl;

    //cout<<“DoubleStack is pop!”<<endl;
    //double popDoubleValue;
    //while(b.pop(popDoubleValue)){
    //    cout<<popDoubleValue<<” “;
    //}
    //cout<<“\nDoubleStack is empty!”<<endl;

    Stack<int> a(5);
    Stack<double> b;//默认构造函数

    testStack(a, 1, 1,”stack_a”);//模板函数来测试模板类
    testStack(b, 1.1, 1.1, “stack_b”);

}

注:main()函数中的注释了的代码为相应的测试类模板测试代码,而最后面则采用了更高级的一种方式(即采用函数模板来测试相应的类模板。函数模板的定义在main()函数最上面(注意:函数模板不能定义在相应的main()函数中,否则会提示错误信息)。