C++中的代码重用
- 类模板
可以定义专门用于存储double值或string对象的Stack类,除了保存的对象类型不同外,这两种Stack类的代码是相同的。 然而,与其编写新的类声明,不如编写一个泛型(即独立于类型的)栈,然后将具体的类型作为参数传递给这个类。
- 定义模板类
和模板函数一样,模板类以下面这样的代码开头:
template <class Type>
关键字template告诉编译器,将要定义一个模板。 尖括号中的内容相当于函数的参数列表。 可以把关键字class看作是变量的类型名,该变量接受类型作为其值,把Type看作是该变量的名称。
//stacktp.h -- 栈模板
#ifndef STACKTP_H_
#define STACKTP_H_
template<class Type>
class Stack
{
private:
enum { MAX = 10 };
Type items[MAX];
int top;
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type & item);
bool pop(Type & 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 // !STACKTP_H_
- 使用模板类
仅在程序包含模板并不能生成模板类,而必须请求实例化。 为此,需要声明一个类型为模板类的对象,方法是使用所需的具体类型替代泛型名。 例如,下面的代码创建两个栈,一个用于存储int,另一个用于存储string对象:
Stack<int> kernels;
Stack<string> colonels;
看到上述声明后,编译器将按Stack<Type>模板来生成两个独立的类声明和两组独立的类方法。
泛型标识符——例如这里的Type——成为类型参数,这意味着它们类似于变量,但赋给它们的不能是数字,而只能说类型。
注意,必须显示地提供所需的类型,这与常规的函数模板是不同的,因为编译器可以根据函数的参数类型来确定要生成哪种函数。
//stacktp.h -- 栈模板
#ifndef STACKTP_H_
#define STACKTP_H_
template<class Type>
class Stack
{
private:
enum { MAX = 10 };
Type items[MAX];
int top;
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type & item);
bool pop(Type & 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 // !STACKTP_H_
//stacktem.cpp -- 测试template stack类
#include<iostream>
#include<string>
#include<cctype>
#include"stacktp.h"
using std::cin;
using std::cout;
int main()
{
Stack<std::string>st; //创建一个空栈
char ch;
std::string po;
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
while (cin >> ch && std::toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!std::isalpha(ch))
{
cout << '\a';
continue;
}
switch (ch)
{
case'A':
case'a':
cout << "Enter a PO number to add: ";
cin >> po;
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p':
if (st.isempty())
cout << "stack alreay empty\n";
else
{
st.pop(po);
cout << "PO #"<<po<< " popped\n";
break;
}
}
cout << "Please enter A to add a purchase order,\n"
<< "p to process a PO, or Q to quit.\n";
}
cout << "Bye.\n";
system("pause");
return 0;
}
- 深入探讨模板类
下列程序重新定义了Stack<Type>类,使Stack构造函数能接受一个可选大小的参数。 这涉及到在内部使用动态数组。 因此,Stack类需要包含一个析构函数、一个复制构造函数和一个赋值运算符。
//stacktp1.h -- 栈模板
#ifndef STACKTP_H_
#define STACKTP_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)
{
items = new Type[stacksize];
}
template<class Type>
Stack<Type>::Stack(const Stack & 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;
}
else
return false;
}
template<class Type>
bool Stack<Type>::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
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.item[i];
return *this;
}
#endif // !STACKTP_H_
//stkoptr1.cpp -- 测试指针栈
#include<iostream>
#include<cstdlib>
#include<ctime>
#include"stacktp1.h"
const int Num = 10;
int main()
{
std::srand(std::time(0));
std::cout << "Please enter stack size: ";
int stacksize;
std::cin >> stacksize;
//创建一个大小为stacksize的空栈
Stack<const char *>st(stacksize);
//入栈
const char * in[Num] = {
"1: Hank Gilgamesh", "2: Kiki Ishtar",
"3: Betty Rocker","4: Ian Flagranti",
"5: Wolfgang Kibble", "6: Portia Koop",
"7: Joy Almodo", "8: Xaverie Paprika",
"9: Juan Moore","10: Misha Mache"
};
//出栈
const char *out[Num];
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";
system("pause");
return 0;
}