Мы достигаем этого, включая в обращение параметр шаблона. Таким образом, имена в определении Array_RC разрешаются тогда, когда определяется шаблон (за исключением имен, явно зависящих от его параметра). Если встречается неквалифицированное имя _size, то компилятор должен найти его определение, если только это имя не зависит явно от параметра шаблона. Мы сделали имя _size зависящим от параметра шаблона, предварив его именем базового класса Array. Теперь компилятор не будет пытаться разрешить имя _size до момента конкретизации шаблона. (В определении класса Array_Sort мы приведем другие примеры использования подобных приемов.)

Каждая конкретизация Array_RC порождает экземпляр класса Array. Например:

Array_RCstring sa;

конкретизирует параметром string как шаблон Array_RC, так и шаблон Array. Приведенная ниже программа вызывает try_array() (реализацию см. в разделе 16.13), передавая ей объекты подтипа Array_RC. Если все сделано правильно, то выходы за границы массивы будут замечены:

#include "Array_RC.C"

#include "try_array.C"

int main()

{

static int ia[] = { 12,7,14,9,128,17,6,3,27,5 };

cout "конкретизация шаблона класса Array_RC int\n";

try_array( iA );

return 0;

}

После компиляции и запуска программа печатает следующее:

конкретизация шаблона класса Array_RCint

try_array: начальные значения массива

( 10 ) 12, 7, 14, 9, 128, 17

6, 3, 27, 5

try_array: после присваиваний

( 10 ) 128, 7, 14, 9, 128, 128

6, 3, 27, 3

try_array: почленная инициализация

( 10 ) 12, 7, 14, 9, 128, 128

6, 3, 27, 3

try_array: после почленного копирования

( 10 ) 12, 7, 128, 9, 128, 128

6, 3, 27, 3

try_array: после вызова grow

( 10 ) 12, 7, 128, 9, 128, 128

6, 3, 27, 3, 0, 0

0, 0, 0, 0

искомое значение: 5 возвращенный индекс: -1

Assertion failed: ix = 0 && ix & _size

<p>18.6.2. Порождение класса отсортированного массива</p>

Вторая наша специализация класса Array – отсортированный подтип Array_Sort. Мы поместим его определение в заголовочный файл Array_S.h:

#ifndef ARRAY_S_H_

#define ARRAY_S_H_

#include "Array.h"

template class Type

class Array_Sort : public virtual Array Type {

protected:

void set_bit() { dirty_bit = true; }

void clear_bit() { dirty_bit = false; }

void check_bit() {

if ( dirty_bit ) {

sort( 0, Array Type::_size-1 );

clear_bit();

}

}

public:

Array_Sort( const Array_Sort& );

Array_Sort( int sz = Array Type::ArraySize )

: Array Type( sz )

{ clear_bit(); }

Array_Sort( const Type* arr, int sz )

: Array Type( arr, sz )

{ sort( 0,Array Type::_size-1 ); clear_bit(); }

Type& operator[]( int ix )

{ set_bit(); return ia[ ix ]; }

void print( ostream& os = cout ) const

{ check_bit(); Array Type::print( os ); }

Type min() { check_bit(); return ia[ 0 ]; }

Type max() { check_bit(); return ia[ Array Type::_size-1 ]; }

bool is_dirty() const { return dirty_bit; }

int find( Type );

void grow();

protected:

bool dirty_bit;

};

#endif

Array_Sort включает дополнительный член – dirty_bit. Если он установлен в true, то не гарантируется, что массив по-прежнему отсортирован. Предоставляется также ряд вспомогательных функций доступа: is_dirty() возвращает значение dirty_bit; set_bit() устанавливает dirty_bit в true; clear_bit() сбрасывает dirty_bit в false; check_bit() пересортировывает массив, если dirty_bit равно true, после чего сбрасывает его в false. Все операции, которые потенциально могут перевести массив в неотсортированное состояние, вызывают set_bit().

При каждом обращении к шаблону Array необходимо указывать полный список параметров.

Перейти на страницу:

Похожие книги