Ключевые слова class и typename имеют одинаковое значение, можно использовать любое из них. Более удобное для запоминания typename появилось в стандарте С++ сравнительно недавно и поддерживается еще не всеми компиляторами. Поскольку наши тексты были написаны до появления этого ключевого слова, в них употребляется class. Шаблон класса list_item выглядит так:

template class elemType

class list_item {

public:

list_item( elemType value, list_item *item = 0 )

: _value( value ) {

if ( !item )

_next = 0;

else {

_next = item-_next;

item-_next = this;

}

}

elemType value() { return _value; }

list_item* next() { return _next; }

void next( list_item *link ) { _next = link; }

void value( elemType new_value ) { _value = new_value; }

private:

elemType _value;

list_item *_next;

};

Все упоминания типа int в определении класса ilist_item заменены на параметр elemType. Когда мы пишем:

list_itemdoub1e *ptr = new list_itemdoub1e( 3.14 );

компилятор подставляет double вместо elemType и создает экземпляр list_item, поддерживающий данный тип.

Аналогичным образом модифицируем класс ilist в шаблон класса list:

template class elemType

class list {

public:

list()

: _at_front( 0 ), _at_end( 0 ), _current( 0 ),

_size( 0 ) {}

1ist( const list );

list operator=( const list );

~list() { remove_all(); }

void insert ( list_itemelemType *ptr, elemType value );

void insert_end( elemType value );

void insert_front( elemType value );

void insert_all( const list rhs );

int remove( elemType value );

void remove_front();

void remove_all();

list_itemelemType *find( elemType value );

list_itemelemType *next_iter();

list_itemelemType* init_iter( list_itemelemType *it );

void disp1ay( ostream os = cout );

void concat( const list );

void reverse ();

int size() { return _size; }

private:

void bump_up_size() { ++_size; }

void bump_down_size() { --_size; }

list_itemelemType *_at_front;

1ist_itemelemType *_at_end;

list_itemelemType *_current;

int _size;

};

Объекты шаблона класса list используются точно так же, как и объекты класса ilist. Основное преимущество шаблона в том, что он обеспечивает поддержку произвольных типов данных с помощью единственного определения.

(Шаблоны являются важной составной частью концепции программирования на С++. В главе 6 мы рассмотрим набор классов контейнерных типов, предоставляемых стандартной библиотекой С++. Неудивительно, что она содержит шаблон класса, реализующего операции со списками, равно как и шаблон класса, поддерживающего векторы; мы рассматривали их в главах 2 и 3.)

Наличие класса списка в стандартной библиотеке представляет некоторую проблему. Мы выбрали для нашей реализации название list, но, к сожалению, стандартный класс также носит это название. Теперь мы не можем использовать в программе одновременно оба класса. Конечно, проблему решит переименование нашего шаблона, однако во многих случаях эта возможность отсутствует.

Более общее решение состоит в использовании механизма пространства имен, который позволяет разработчику библиотеки заключить все свои имена в некоторое поименованное пространство и таким образом избежать конфликта с именами из глобального пространства. Применяя нотацию квалифицированного доступа, мы можем употреблять эти имена в программах. Стандартная библиотека С++ помещает свои имена в пространство std. Мы тоже поместим наш код в собственное пространство:

namespace Primer_Third_Edition

{

template typename elemType

class list_item{ ... };

template typename elemType

class list{ ... };

// ...

}

Для использования такого класса в пользовательской программе необходимо написать следующее:

// наш заголовочный файл

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

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