// определение Queue и его функций-членов
}
// объявление специализации
// cplusplus_primer::Queuechar*
template class cplusplus_primer::Queueprimer::Queuechar* и функции-члена remove() для класса cplusplus_primer::Queue находятся в глобальной области видимости. Поскольку такая область содержит пространство имен cplusplus_primer, а имена специализаций квалифицированы его именем, то определения специализаций для шаблона Queue вполне законны.
16.13. Шаблон класса Array
В этом разделе мы завершим реализацию шаблона класса Array, введенного в разделе 2.5 (этот шаблон будет распространен на одиночное наследование в разделе 18.3 и на множественное наследование в разделе 18.6). Так выглядит полный заголовочный файл:
#ifndef ARRAY_H
#define ARRAY_H
#include iostream
template class elemType class Array;
template class elemType ostream&
operator( ostream &, Array&elemType& & );
template class elemType
class Array {
public:
explicit Array( int sz = DefaultArraySize )
{ init( 0, sz ); }
Array( const elemType *ar, int sz )
{ init( ar, sz ); }
Array( const Array &iA )
{ init( iA._ia, iA._size ); }
~Array() { delete[] _ia; }
Array & operator=( const Array & );
int size() const { return _size; }
elemType& operator[]( int ix ) const
{ return _ia[ix]; }
ostream &print( ostream& os = cout ) const;
void grow();
void sort( int,int );
int find( elemType );
elemType min();
elemType max();
private:
void init( const elemType*, int );
void swap( int, int );
static const int DefaultArraySize = 12;
int _size;
elemType *_ia;
};
#endif
Код, общий для реализации всех трех конструкторов, вынесен в отдельную функцию-член init(). Поскольку она не должна напрямую вызываться пользователями шаблона класса Array, мы поместили ее в закрытую секцию:
template class elemType
void ArrayelemType::init( const elemType *array, int sz )
{
_size = sz;
_ia = new elemType[ _size ];
for ( int ix = 0; ix _size; ++ix )
if ( ! array )
_ia[ ix ] = 0;
else _ia[ ix ] = array[ ix ];
}
Реализация копирующего оператора присваивания не вызывает затруднений. Как отмечалось в разделе 14.7, в код включена защита от копирования объекта в самого себя:
template class elemType ArrayelemType&
ArrayelemType::operator=( const ArrayelemType&iA )
{
if ( this != &iA ) {
delete[] _ia;
init( iA._ia, iA._size );
}
return *this;
}
Функция-член print() отвечает за вывод объекта того типа, которым конкретизирован шаблон Array. Возможно, реализация несколько сложнее, чем необходимо, зато данные аккуратно размещаются на странице. Если экземпляр конкретизированного класса Array содержит элементы 3, 5, 8, 13 и 21, то выведены они будут так:
(5) 3, 5, 8, 13, 21
Оператор потокового вывода просто вызывает print(). Ниже приведена реализация обеих функций:
template class elemType ostream&
operator( ostream &os, Array&elemType& &ar )
{
return ar.print( os );
}
template class elemType
ostream & Array&elemType&::print( ostream &os ) const
{
const int lineLength = 12;
os "( " _size " ) ";
for ( int ix = 0; ix _size; ++ix )
{
if ( ix % lineLength == 0 && ix )
os "\n\t";
os _ia[ ix ];
// не выводить запятую за последним элементом в строке,
// а также за последним элементом массива
if ( ix % lineLength != lineLength-1 && ix != _size-1 )
os ", ";
}
os " \n";
return os;
}