- •3.8. Упражнения 49
- •Введение
- •1. Базовые элементы
- •1.1. Комментарии
- •1.2. Функция «main»
- •1.3. Идентификаторы и пространства имен
- •1.4. Типы
- •1.5. Переменные
- •1.7. Константы
- •1.6. Преобразование типов
- •1.8. Потоковый ввод – вывод
- •1.9. Операции
- •1.9.1. Арифметические операции
- •1.9.2. Поразрядные операции
- •1.9.3. Условный оператор
- •1.9.4. Операции отношения
- •1.9.5. Логические операции
- •1.10. Стандартные математические функции
- •1.11. Упражнения
- •2. Базовые конструкции
- •2.1 Ветвление
- •2.1.1. Конструкция «if – else»
- •2.1.2. Конструкция «switch»
- •2.2. Циклы
- •2.2.1. Цикл «for»
- •2.2.2. Цикл «while»
- •2.2.3. Цикл «do – while»
- •2.2.4. Операторы циклов
- •2.2.5. Вложенность
- •2.3. Упражнения
- •2.3.1. Ветвления
- •2.3.2. Циклы
- •2.3.3. Вложенность
- •3. Указатели. Массивы. Структуры
- •3.1. Указатели
- •3.2. Массивы
- •3.2.1. Статические массивы
- •3.2.2. Динамические массивы
- •3.4. Ссылки
- •3.5. Структуры
- •3.6. Объединение
- •3.7. Переопределение типов
- •3.8. Упражнения
- •3.8.1. Статические и динамические массивы
- •3.8.2. Многомерные массивы
- •3.8.3. Строки
- •4. Функции
- •4.1. Простые функции
- •4.2. Рекурсия
- •4.3. Указатели и ссылки
- •4.3.1. Передаваемые параметры
- •4.3.2. Возвращаемые значения
- •4.3.3. Ссылки и структуры в функциях
- •4.3.4. Указатели и массивы в функциях
- •4.3.5. Указатели и ссылки на функцию
- •4.4. Шаблоны функций
- •4.5. Упражнения
- •4.5.1. Простые функции
- •4.5.2. Параметры – ссылки и параметры — указатели
- •5. Стандартные классы
- •5.1. Класс «pair»
- •5.2. Класс «complex»
- •5.3. Класс «string»
- •5.4. Контейнеры. Алгоритмы. Итераторы
- •5.5. Класс «vector»
- •5.6. Упражнения
- •5.6.1. Класс «string»
- •5.6.2. Класс «vector»
- •6. Файловый ввод – вывод
- •6.1. Операции
- •6.2. Методы
- •6.3. Флаги
- •6.4. Двоичный режим
- •6.5. Упражнения
- •Ллитература
4.4. Шаблоны функций
Одной из наиболее частых проблем при реализации тех или иных функций является их зависимость от типа входных параметров и возвращаемых значений. Так, например, функция нахождения большего из двух чисел должна быть представлена в нескольких вариантах – для каждого из встроенных типов, что сильно загромождает код. Более того, в ряде случаев, когда, например, подключается пользовательская библиотека набора одних и техже функций для разных типов данных, некоторые из них в программе могут никогда и не вызываться.
Разрешение подобных ситуаций возможно посредством механизма шаблонов. Шаблонизированные функции, по сути, являются функциями, в которых тип данных представлен в качестве параметра. Из одного шаблона может быть сгенерирован код множества функций, где параметрами шаблона могут быть не только встроенные типы, но и стандартные или разработанные пользователем классы.
Важным в механизме шаблонов является работа компилятора. В тот момент, как он встречает в коде шаблон функции, генерации кода – конкретизации шаблона – не происходит. Это связано с тем, что компилятор в этот момент не знает какой конкретный вариант функции будет вызван. В связи с этим генерация кода происходит в момент вызова функции, когда известны все параметры, на основании которых и происходит вывод аргументов шаблона.
У шаблона может быть несколько параметров, которые должны следовать через запятую.
Листинг 4.11. Шаблоны функций.
#include <iostream>
using namespace std;
//шаблон с идентификатором типа элементов массива arelem;
//и размера массива arsize;
template <class arelem, class arsize>
//тип размера не является шаблонным параметром;
arsize find (arelem ar[], arsize size, arelem & element)
{
//поиск позиции первого вхождения заданного элемента;
arsize ret_pos = -1;
for (long i = 0; i < size; i++)
if (ar[i] == element) {
ret_pos = i;
break;
}
return ret_pos;
}
int main(void)
{
long size;
cin >> size;
double *pinta = new double[size];
for (long i = 0; i < size; i++)
pinta[i] = i;
double value;
cin >> value;
cout << find(pinta, size, value) << endl;
delete[] pinta;
char* str = "string like array";
char ch;
cin >> ch;
cout << find(str, 17, ch) << endl;
return 0;
}
Шаблон предоставляет возможность функции иметь тип параметров или тип возвращаемого значения, не являющийся шаблонным параметром. Другой возможностью является явное задание типов, которое используется при невозможности автоматического вывода аргументов шаблона. Эти типы задаются в угловых скобках через запятую, при этом хвостовые параметры могут опускаться.
Листинг 4.12. Явное задание аргументов шаблона.
#include <iostream>
using namespace std;
template <class retype, class atype, class btype>
retype max (atype aval, btype bval)
{
return aval > bval ? aval : bval;
}
int main(void)
{
short x = 11;
float y = 11.3;
//первый аргумент – возвращаемый тип — double;
//оставшиеся выведутся автоматически;
cout << max<double>(x, y) << endl;
return 0;
}
