Выбрать главу

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;

}

Вывод значения элемента массива в функции print() осуществляет такая инструкция:

os _ia[ ix ];

Для ее правильной работы должно выполняться требование к типам, которыми конкретизируется шаблон Array: такой тип должен быть встроенным либо иметь собственный оператор вывода. В противном случае любая попытка распечатать содержимое класса Array приведет к ошибке компиляции в том месте, где используется несуществующий оператор.

Функция-член grow() увеличивает размер объекта класса Array. В нашем примере - в полтора раза:

template class elemType

void Array elemType::grow()

{

elemType *oldia = _ia;

int oldSize = _size;

_size = oldSize + oldSize/2 + 1;

_ia = new elemType[_size];

int ix;

for ( ix = 0; ix oldSize; ++ix )

_ia[ix] = oldia[ix];

for ( ; ix _size; ++ix )

_ia[ix] = elemType();

delete[] oldia;

}

Функции-члены find(), min() и max() осуществляют последовательный поиск во внутреннем массиве _ia. Если бы массив был отсортирован, то, конечно, их можно было бы реализовать гораздо эффективнее.

template class elemType

elemType Array elemType ::min( )

{

assert( _ia != 0 );

elemType min_val = _ia[0];

for ( int ix = 1; ix _size; ++ix )

if ( _ia[ix] min_val )

min_val = _ia[ix];

return min_val;

}

template class elemType

elemType Array elemType ::max()

{

assert( _ia != 0 );

elemType max_val = _ia[0];

for ( int ix = 1; ix _size; ++ix )

if ( max_val _ia[ix] )

max_val = _ia[ix];

return max_val;

}

template class elemType

int Array elemType ::find( elemType val )

{

for ( int ix = 0; ix _size; ++ix )

if ( val == _ia[ix] )

return ix;

return -1;

}

В шаблоне класса Array есть функция-член sort(), реализованная с помощью алгоритма быстрой сортировки. Она очень похожа на шаблон функции, представленный в разделе 10.11. Функция-член swap() - вспомогательная утилита для sort(); она не является частью открытого интерфейса шаблона и потому помещена в закрытую секцию: