- •Директивы препроцессора и комментарии
- •Структура программы
- •Переменные
- •Преобразования базовых типов
- •Базовые конструкции структурного программирования
- •Оператор "выражение"
- •Операторы ветвления Условный оператор if
- •If ( выражение ) оператор_1; [else оператор_2;]
- •Оператор switch
- •Массивы
- •Функции
- •Параметры функции
- •Передача массивов в качестве параметров
- •Передача имен функций в качестве параметров
- •Параметры со значениями по умолчанию
- •Модульное программирование
- •Директивы препроцессора
- •Директива #include
- •Директива #define
- •Области действия идентификаторов
- •Внешние объявления
- •Поименованные области
- •Пространства имен стандартной библиотеки
- •Объектно ориентированное программирование
- •Наследование
- •Использование шаблонов классов
- •Достоинства и недостатки шаблонов
- •Практические примеры. Файловые потоки. Пользовательские функции
- •Пользовательские функции
- •Краткие итоги
- •Вопросы
- •Упражнения
Использование шаблонов классов
Чтобы создать при помощи шаблона конкретный объект конкретного класса, при описании объекта после имени шаблона в угловых скобках перечисляются его фактические параметры:
имя_шаблона <фактические параметры> имя_объекта (параметры_конструктора);
Процесс создания конкретного класса из шаблона путем подстановки аргументов называется инстанцированием шаблона.Имя шаблона вместе с фактическими параметрами можно воспринимать как уточненное имя класса. Примеры создания объектов по шаблонам:
List <int> List_int; // список целых чисел
List <double> List_double; // список вещественных чисел
List <monster> List_monster; // список объектов класса monster
Block <char, 128> buf; // блок символов
Block <monstr, 100> stado; // блок объектов класса monster
Pair<int, int> a; // объявление пары целых
Pair<int, double> b; // объявление пары "целый, вещественный"
Pair<int, double> b = { 1, 2.1 }; // объявление с инициализацией
Pair<string, Date> d; // аргументы - пользовательские классы
При использовании параметров шаблона по умолчанию список аргументов может оказаться пустым, при этом угловые скобки опускать нельзя:
template<class T = char> class String;
String<>* p;
Для каждого инстанцированного класса компилятор создает имя, отличающееся и от имени шаблона, и от имен других инстанцированных классов. Тем самым каждый инстанцированный класс определяет отдельный тип. В классе-шаблоне разрешено объявлять статические методы и статические поля, однако следует учесть, что каждый инстанцированный класс обладает собственной копией статических элементов.
После создания объектов с ними можно работать так же, как с объектами обычных классов, например:
for (int i = 1; i<10; i++)List_double.add(i*0.08);
List_double.print();
//----------------------------------
for (int i = 1; i<10; i++)List_monster.add(i);
List_monster.print();
//----------------------------------
strcpy(buf, "Очень важное сообщение");
cout << buf << endl;
Для упрощения использования шаблонов классов можно применить переименование типов с помощью typedef:
typedef List <double> Ldbl;
Ldbl List_double;
Достоинства и недостатки шаблонов
Шаблоны представляют собой мощное и эффективное средство обращения с различными типами данных, которое можно назвать параметрическим полиморфизмом, обеспечивают безопасное использование типов, в отличие от макросов препроцессора, и являются вкупе с шаблонами функций средством реализации идей обобщенного программирования и метапрограммирования. Однако следует иметь в виду, что эти средства предназначены для грамотного использования и требуют знания многих тонкостей. Программа, использующая шаблоны, содержит код для каждого порожденного типа, что может увеличить размер исполняемого файла. Кроме того, с одними типами данных шаблоны могут работать не так эффективно, как с другими. В этом случае имеет смысл использовать специализацию шаблона (о специализации шаблонов можно прочитать в учебнике [18]).
Стандартная библиотека С++ предоставляет большой набор шаблонов для различных способов организации хранения и обработки данных.
