Функции-члены шаблонов Queue и QueueItem
Чтобы понять, как определяются и используются функции-члены шаблонов классов, продолжим изучение шаблонов Queue и QueueItem:
template <class Type>
class Queue {
public:
Queue() : front( 0 ), back ( 0 ) { }
~Queue();
Type& remove();
void add( const Type & );
bool is_empty() const {
return front == 0;
}
private:
QueueItem<Type> *front;
QueueItem<Type> *back;
};
Деструктор, а также функции-члены remove() и add() определены не в теле шаблона, а вне его. Деструктор Queue опустошает очередь:
template <class Type>
Queue<Type>::~Queue()
{
while (! is_empty() )
remove();
}
Функция-член Queue<Type>::add() помещает новый элемент в конец очереди:
template <class Type>
void Queue<Type>::add( const Type &val )
{
// создать новый объект QueueItem
QueueItem<Type> *pt =
new QueueItem<Type>( val );
if ( is_empty() )
front = back = pt;
else
{
back->next = pt;
back = pt;
}
}
Функция-член Queue<Type>::remove() возвращает значение элемента, находящегося в начале очереди, и удаляет сам элемент.
#include <iostream>
#include <cstdlib>
template <class Type>
Type Queue<Type>::remove()
{
if ( is_empty() )
{
cerr << "remove() вызвана для пустой очереди\n";
exit( -1 );
}
QueueItem<Type> *pt = front;
front = front->next;
Type retval = pt->item;
delete pt;
return retval;
}
Мы поместили определения функций-членов в заголовочный файл Queue.h, включив его в каждый файл, где возможны конкретизации функций. (Обоснование этого решения, а также рассмотрение более общих вопросов, касающихся модели компиляции шаблонов, мы отложим до раздела 16.8.)
В следующей программе иллюстрируется использование и конкретизация функции-члена шаблона Queue:
#include <iostream>
#include "Queue.h"
int main()
{
// конкретизируется класс Queue<int>
// оператор new требует, чтобы Queue<int> был определен
Queue<int> *p_qi = new Queue<int>;
int ival;
for ( ival = 0; ival < 10; ++ival )
// конкретизируется функция-член add()
p_qi->add( ival );
int err_cnt = 0;
for ( ival = 0; ival < 10; ++ival ) {
// конкретизируется функция-член remove()
int qval = p_qi->remove();
if ( ival != qval ) err_cnt++;
}
if ( !err_cnt )
cout << "!! queue executed ok\n";
else cerr << "?? queue errors: " << err_cnt << endl;
return 0;
}
После компиляции и запуска программа выводит следующую строку:
!! queue executed ok
Упражнение 16.5
Используя шаблон класса Screen, определенный в разделе 16.2, реализуйте функции-члены Screen (см. разделы 13.3, 13.4 и 13.6) в виде функций-членов шаблона.