// ...
}
16.1.1. Определения шаблонов классов Queue и QueueItem
Ниже представлено определение шаблона класса Queue. Оно помещено в заголовочный файл Queue.h вместе с определением шаблона QueueItem:
#ifndef QUEUE_H
#define QUEUE_H
// объявление QueueItem
template class T class 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:
QueueItemType *front;
QueueItemType *back;
};
#endif
При использовании имени Queue внутри определения шаблона класса Queue список параметров Type можно опускать. Однако пропуск списка параметров шаблона QueueItem в определении шаблона Queue недопустим. Так, объявление члена front является ошибкой:
template class Type
class Queue {
public:
// ...
private:
// ошибка: список параметров для QueueItem неизвестен
QueueItemType *front;
}
Упражнение 16.1
Найдите ошибочные объявления (или пары объявлений) шаблонов классов:
(a) template class Type
class Container1;
template class Type, int size
class Container1;
(b) template class T, U, class V
class Container2;
(c) template class C1, typename C2
class Container3 {};
(d) template typename myT, class myT
class Container4 {};
(e) template class Type, int *pi
class Container5;
(f) template class Type, int val = 0
class Container6;
template class T = complexdouble, int v
class Container6;
Упражнение 16.2
Следующее определение шаблона List некорректно. Как исправить ошибку?
template class elemenType
class ListItem;
template class elemType
class List {
public:
ListelemType()
: _at_front( 0 ), _at_end( 0 ), _current( 0 ), _size( 0 )
{}
ListelemType( const ListelemType & );
ListelemType& operator=( const ListelemType & );
~List();
void insert( ListItem *ptr, elemType value );
int remove( elemType value );
ListItem *find( elemType value );
void display( ostream &os = cout );
int size() { return _size; }
private:
ListItem *_at_front;
ListItem *_at_end;
ListItem *_current;
int _size
};
16.2. Конкретизация шаблона класса
В определении шаблона указывается, как следует строить индивидуальные классы, если заданы один или более фактических типов или значений. По шаблону Queue автоматически генерируются экземпляры классов Queue с разными типами элементов. Например, если написать:
Queueint qi;
то из обобщенного определения шаблона автоматически создается класс Queue для объектов типа int.
Генерация конкретного класса из обобщенного определения шаблона называется конкретизацией шаблона. При такой конкретизации Queue для объектов типа int каждое вхождение параметра Type в определении шаблона заменяется на int, так что определение класса Queue принимает вид:
template class int
class Queue {
public:
Queue() : front( 0 ), back ( 0 ) { }
~Queue();
int& remove();
void add( const int & );
bool is_empty() const {
return front == 0;
}
private:
QueueItemint *front;
QueueItemint *back;
};
Чтобы создать класс Queue для объектов типа string, надо написать:
Queuestring qs;
При этом каждое вхождение Type в определении шаблона будет заменено на string. Объекты qi и qs являются объектами автоматически созданных классов.
Каждый конкретизированный по одному и тому же шаблону экземпляр класса совершенно не зависит от всех остальных. Так, у Queue для типа int нет никаких прав доступа к неоткрытым членам того же класса для типа string.