首页 > 代码库 > 类模板使用说明

类模板使用说明

类模板声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//通常形式
template <typename TypeParam>
class SomeClass
{
    //...SomeClass的成员
};
 
//或者
 
template <typename TypeParam1,...,typename TypeParamn>
class SomeClass
{
    //...SomeClass的成员
};


   在这些形式中,TypeParam是命名将要存储在容器类SomeClass中的数据的类型的通用类型参数,而关键词typename可以被替换为class。

   注意

        ??1.关键词template规定了后面接着的是一个类的模式,而不是一个实际的类声明

    ?    ?2.在类型形参列表中关键词tpyename和class可以互换使用

    ?    ?3.和规则类的函数成员不同,在使用类模板时,编译器必须能够找到他的函数成员的定义。一种通常的方法是将所有函数定义从实现文件ClassName.cpp中移到ClassName.h中类声明后面。另一种方法是将函数定义放在单独的文件中然后再ClassName.h的最后#include这个文件。

    ?    ?一个类模板仅仅是描述如何根据给定的类型那个构建不同的类的一个模式,这个创建一个类的过程被称为实例化。这是通过附加一个实际类型到对象定义中的类名上来实现的:

1
SomeClass<Actual_Type> object;

    ?    ?例如,可以使用下面的定义来实例化Stack这个类模板:

1
2
Stack<char> charStack;
Stack<char> dubStack;

    ?    ?当编译器处理这些声明时,他将产生两个不同的Stack类(两个实例),一个是使用char代替了StackElement,另一个是使用double代替了StackElement。第一个类中的构造函数将构造charStack为一个空的字符型的栈,而第二个类中的构造函数将构造dubStack为一个空的double型的栈。

有3条重要的规则规定了如何创建类模板:

    ?    ?1.所有定义在类声明之外的操作都必须是模板函数

    ?    ?2.任何将一个模板类的名作为类型的使用都必须参数化

    ?    ?3.当使用类模板时,编译器必须能够找到它的操作的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template <typename StackElement>
class Stack
{
    //复制构造函数
    Stack(const Stack<StackElement>& original);
    //赋值运算符
    const Stack<StackElement>& operator=(const Stack<StackElement>& original);
    //somecode
};
 
template <typename StackElement>
Stack<StackElement>::Stack()
{
    // 构造函数的定义
}
 
template <typename StackElement>
Stack<StackElement>::Stack(const Stack<StackElement>& original)
{
    //复制构造函数
}
 
//---operator<<()
template <typename StackElement>
inline ostream& operator<<(ostream& out,const Stack<StackElement>& st)
{
    //somecode
}


一个Stack类模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <cassert>
 
using namespace std;
 
#ifndef DSTACK
#define DSTACK
 
template <typename StackElement>
class Stack
{
public:
    Stack(int numElements = 128);
    Stack(const Stack<StackElement>& original);
    ~Stack();
 
    const Stack<StackElement>& operator =(const Stack<StackElement>& rightHandSide);
 
    bool empty() const;
    void push(const StackElement& value);
    void display(ostream& out) const;
    StackElement top() const;
    void pop();
private:
    int myCapacity;
    int myTop;
    StackElement* myArray;
};


对应的cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <new>
 
template <typename StackElement>
Stack<StackElement>::Stack(int numElements)
{
    assert(numElements>0);
    myCapacity = numElements;
    myArray = new(nothrow) StackElement[myCapacity];
    if(myArray != 0)
        myTop = -1;
    else
    {
        cerr << "Inadequate memort to allocate stack !\n" << " -- terminating execution !\n";
        exit(1);
    }
}
 
template <typename StackElement>
Stack<StackElement>::Stack(const Stack<StackElement> &original):myCapacity(original.myCapacity),myTop(original.myTop)
{
    myArray = new(nothrow) StackElement[myCapacity];
    if(myArray != 0)
        for(int pos=0;pos<=myTop;pos++)
            myArray[pos] = original.myArray[pos];
    else
    {
        cerr << "Inadequate memort to allocate stack !\n";
        exit(1);
    }
}
 
template <typename StackElement>
inline Stack<StackElement>::~Stack()
{
    delete[] myArray;
}
 
 
template <typename StackElement>
const Stack<StackElement>& Stack<StackElement>::operator =(const Stack<StackElement>& rightHandSide)
{
    if(this != &rightHandSide)
    {
        if(myCapacity != rightHandSide.myCapacity)
        {
            delete[] myArray;
 
            myCapacity = rightHandSide.myCapacity;
            myArray = new StackElement[myCapacity];
            if(myArray == 0)
            {
                cerr << "Inadequate memory !\n";
                exit(1);
            }
        }
 
        myTop = rightHandSide.myTop;
        for(int pos=0;pos<=myTop;pos++)
            myArray[pos] = rightHandSide.myArray[pos];
    }
    return *this;
}
 
template <typename StackElement>
inline bool Stack<StackElement>::empty() const
{
    return (myTop == -1);
}
 
template <typename StackElement>
inline void Stack<StackElement>::push(const StackElement &value)
{
    if(myTop < myCapacity-1)
    {
        ++myTop;
        myArray[myTop] = value;
    }
    else
    {
        cerr << "Stack full, can‘t add new value‘ !\n";
        exit(1);
    }
}
 
template <typename StackElement>
inline void Stack<StackElement>::display(ostream &out) const
{
    for(int i=myTop;i>=0;i--)
        out << myArray[i] << endl;
}
 
template <typename StackElement>
inline ostream& operator <<(ostream& out,const Stack<StackElement>& st)
{
    st.display(out);
    return out;
}
 
template <typename StackElement>
inline StackElement Stack<StackElement>::top() const
{
    if(!empty())
        return (myArray[myTop]);
    else
    {
        cerr << "Stack is empty -- returning garbage value\n";
        StackElement garbage;
        return garbage;
    }
}
 
template <typename StackElement>
inline void Stack<StackElement>::pop()
{
    if(myTop >= 0)
        myTop--;
    else
        cerr << "Stack is empty -- can‘t remove a value\n";
}

?