1. 定义类模板
程序清单类模板-1列出了类模板和成员函数模板,明确这些模板不是类和成员函数定义很重要,因为它们是C++编译指令,说明了如何生成类和成员函数定义。
不能将模板成员函数放在独立的实现文件中,由于模板不是函数,它们不能单独编译,模板必须与特定的模板实例化请求一起使用。因此,最简单的方式是将所有模板信息放在一个头文件中,并再要使用这些模板的文件中包含该头文件。
//程序清单 类模板-1
//stacktp.h
#ifndef STACKTP_H_
#define STACKTP_H_
template<class Type>
class Stack
{
private:
enum {MAX = 10}; //Stack类拥有的常量
Type items[MAX];
int top;
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type& item); //add item to stack
bool pop(Type& item); //pop top into item
};
template<class Type>
Stack<Type>::Stack()
{
top = 0;
}
template<class Type>
bool Stack<Type>::isempty()
{
return top == 0;
}
template<class Type>
bool Stack<Type>::isfull()
{
return top == MAX;
}
template<class Type>
bool Stack<Type>::push(const Type& item)
{
if(top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
template<class Type>
bool Stack<Type>::pop(Type& item)
{
if(top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
#endif
注意模板成员函数定义与类模板声明一起放在模板的头文件中。
2. 使用模板类
仅在程序中包含模板并不能生成模板类,必须请求实例化,必须显式地提供所需的类型。
Stack<int> kernels;
Stack<std::string> colonels;
3. 深入探讨模板类
正确使用指针栈的方法之一是,让调用程序提供一个指针数组,其中每个指针都指向不同的字符串。注意,栈的任务是管理指针,不是创建指针。程序清单类模板-2重新定义了Stack<Type>类,使Stack构造函数能够接受一个可选大小的参数。这涉及到在内部使用动态数组,因此Stack类需要包含一个析构函数、一个复制构造函数和一个赋值运算符。
//程序清单 类模板-2
//stcktp1.h
#ifndef STCKTP1_H_
#define STCKTP1_H_
template<class Type>
class Stack
{
private:
enum {SIZE = 10}; //默认大小
int stacksize;
Type* items;
int top;
public:
explicit Stack(int ss = SIZE);
Stack(const Stack& st);
~Stack() { delete[] items; }
bool isempty() { return top == 0; }
bool isfull() { return top == stacksize; }
bool push(const Type& item);
bool pop(Type& item);
Stack& operator=(const Stack& st);
};
template<class Type>
Stack<Type>::Stack(int ss): stacksize(ss), top(0)
{
item = new Type[stacksize];
}
template<class Type>
Stack<Type>::Stack(const Stack<Type>& st)
{
stacksize = st.stacksize;
top = st.top;
items = new Type[stacksize];
for(int i = 0; i < top; i++)
{
items[i] = st.items[i];
}
}
template<class Type>
bool Stack<Type>::push(const Type& item)
{
if(top < stacksize)
{
items[top++] = item;
return true;
}
return false;
}
template<class Type>
bool Stack<Type>::pop(Type& item)
{
if(top > 0)
{
item = items[--top];
return true;
}
return false;
}
template<class Type>
Stack<Type>& Stack<Type>::operator=(const Stack<Type>& st)
{
if(this == &st)
return *this;
delete[] items;
stacksize = st.stacksize;
top = st.top;
items = new Type[stacksize];
for(int i = 0; i < top; i++)
{
items[i] = st.items[i];
}
return *this;
}
#endif
程序清单类模板-3使用了这个Stack模板类。
//程序清单 类模板-3
//stkoptr1.cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "stcktp1.h"
const int Num = 10;
int main()
{
std::srand(std::time(0));
std::cout << "Please enter stack size: ";
int stacksize;
std::cin >> stacksize;
//create an empty stack with stacksize siots
Stack<const char*> st(stacksize);
//in basket
const char* in[Num] = {
" 1: Hank Gilgamesh", " 2: Kiki Ishtar",
" 3: Betty Rocker", " 4: Ian Flagranti",
" 5: Wolfgang Kibble", " 6: Portia Koop",
" 7: Joy Almondo", " 8: Xaverie Paprika",
" 9: Juan Moore", " 10: Misha Mache"
};
//out basket
const char* out[Num]; //类型为const char*,因为指针数组被初始化为一组字符串常量
int processed = 0;
int nextin = 0;
while(processed < Num)
{
if(st.isempty())
st.push(in[nextin++]);
else if(st.isfull())
st.pop(out[processed++]);
else if(std::rand() % 2 && nextin < Num)
st.push(in[nextin++]);
else
st.pop(out[processed++]);
}
for(int i = 0; i < Num; i++)
{
std::cout << out[i] << std::endl;
}
std::cout << "Bye\n";
return 0;
}
4. 数组模板示例和非类型参数
模板常用作容器类。
自己设计一个允许指定数组大小的简单数组模板。一种方法是在类中使用动态数组和构造函数参数来提供元素数目,例如程序清单类模板-2;另一种方法是使用模板参数来提供常规数组的大小,C++11新增的模板array就是这样做的,程