Освой самостоятельно С++ за 21 день.
Шрифт:
Благодаря шаблонам, эта проблема легко решается, а с принятием стандарта ANSI шаблоны стали неотъемлемой частью языка C++, подобно которому они сохраняют тип и очень гибки.
Параметризованные типы
С помошью шаблонов можно "научить" компилятор составлять список элементов любого типа, а не только заданного: PartsList — это список частей, CatsList — это список кошек. Единственное отличие между ними — тип элементов списка. При использовании шаблонов тип элементов списка становится параметром для определения класса.
Обшим компонентом практически
Создание экземпляра шаблона
Экземпляризация (instantiation) — это операция создания определенного типа из шаблона. Отдельные классы называются экземплярами шаблона.
Параметризованные шаблоны (parameterized templates) предоставляют возможность создания общего класса и для построения конкретных экземпляров передают этому классу в качестве параметров типы данных.
Объявление шаблона
Объявляем параметризованный объект Array (шаблон для массива) путем записи следующих строк:
1: template <class T> // объявляем шаблон и параметр
2: class Array // параметризуемый класс
3: {
4: public:
5: Array;
6: // здесь должно быть полное определение класса
7: };
Ключевое слово template используется в начале каждого объявления и определения класса шаблона. Параметры шаблона располагаются за ключевым словом template. Параметры — это элементы, которые изменяются с каждым экземпляром. Например, в приведенном выше шаблоне массивов будет изменяться тип объектов, сохраняемых в массиве. Один экземпляр шаблона может хранить массив целых чисел, а другой — массив объектов класса Animals.
В этом примере используется ключевое слово class, за которым следует идентификатор Т. Это ключевое слово означает, что параметром является тип. Идентификатор T используется в остальной части определения шаблона, указывая тем самым на параметризованный тип. В одном экземпляре этого класса вместо идентификатора T повсюду будет стоять тип int, а в другом — тип Cat.
Чтобы объявить экземпляры параметризованного класса Array для типов int и Cat, следует написать:
Array<int> anIntArray;
Array<Cat> aCatArray;
Объект anIntArray представляет собой массив целых чисел, а объект aCatArray — массив элементов типа Cat. Теперь вы можете использовать тип Array<int> в любом месте, где обычно указывается какой-либо тип — для возвращаемого функцией значения, для параметра
функции и т.д. В листинге 19.1 содержится полное объявление уже рассмотренного нами шаблона Array.Примечание:Программа в листинге 19.1 не завершена!
Листинг 19.1. Шаблон класса Array
1: //Листинг 19.1. Шаблон класса массивов
2: #include <iostream.h>
3: const int DefaultSize = 10;
4:
5: template <class T> // объявляем шаблон и параметр
6: class Array // параметризуемый класс
7: {
8: public:
9: // конструкторы
10: Array(int itsSize = DefaultSize);
11: Array(const Array &rhs);
12: ~Array { delete [] pType; }
13:
14: // операторы
15: Array& operator=(const Array&);
16: T& operator[](int offSet) { return pType[offSet]; }
17:
18: // методы доступа
19: int getSize { return itsSize; }
20:
21: private:
22: T *pType;
23: int itsSize;
24: };
Результат:
Результатов нет. Эта программа не завершена.
Анализ: Определение шаблона начинается в строке 5 с ключевого слова template за которым следует параметр. В данном случае параметр идентифицируется как тип за счет использования ключевого слова class, а идентификатор T используется для представления параметризованного типа.
Со строки 6 и до конца определения шаблона (строка 24) вся остальная часть объявления аналогична любому другому объявлению класса. Единственное отличие заключается в том, что везде, где обычно должен стоять тип объекта, используется идентификатор T. Например, можно предположить, что operator[] должен возвращать ссылку на объект в массиве, а на самом деле он объявляется для возврата ссылки на идентификатор типа T.
Если объявлен экземпляр целочисленного массива, перегруженный оператор присваивания этого класса возвратит ссылку на тип integer. А при объявлении экземпляра массива Animal оператор присваивания возвратит ссылку на объект типа Animal.
Использование имени шаблона
Внутри объявления класса слово Array может использоваться без спецификаторов. В другом месте программы этот класс будет упоминаться как Array<T>. Например, если не поместить конструктор внутри объявления класса, то вы должны записать следующее:
template <class T>
Array<T>::Array(int size):
itsSize = size
{
pType = new T[size];
for (int i = 0; i<size; i++)
pType[i] = 0;
}
Объявление, занимающее первую строку этого фрагмента кода, устанавливает в качестве параметра тип данных (class T). В таком случае в программе на шаблон можно ссылаться как Array<T>, а объявленную функцию-член вызывать строкой
Array(int size).
Остальная часть функции имеет такой же вид, какой мог быть у любой другой функции. Это обычный и предпочтительный метод создания класса и его функций путем простого объявления до включения в шаблон.