шаблоны ооп. 7_OOP_шаблоны. Шаблоны функций Шаблоны функций
Скачать 0.68 Mb.
|
Шаблоны функций Шаблоны функций При создании функций иногда возникают ситуации, когда две функции выполняют одинаковый алгоритм обработки данных, но работают с различными типами данных) одна использует параметры типа int, другая типа float). С помощью механизма перегрузки функций можно использовать одно и то же имя для функций, выполняющих разные действия с имеющих разные типы параметров. Пусть есть функция с именем max , которая возвращает максимальное из двух целых значений. Если позже потребуется подобная функция, которая возвращает максимальное значение из двух значений float , то следует определить другую функцию, например, fmax Шаблон определяет набор операторов, позволяющий автоматически генерировать одну и ту же функцию, но для разных типов данных. Шаблон функции определяет типонезависимую функцию. С помощью такого шаблона в дальнейшем можно определить конкретные функции с требуемыми типами. В процессе компиляции компилятор С++ будет автоматически создавать в программе функции с использованием типов, указанных в прототипах функций, которые ссылаются на имя шаблона. 2 Основные положения - Программы часто используют шаблоны функций для быстрого определения функций, которые с помощью одинаковых операторов работают с параметрами разных типов или имеют разные типы возвращаемых значений. - Шаблоны функций имеют специфичные имена. Которые соответствуют имени функции, используемому вами в программе. - После того, как ваша программа определила шаблон функции, она в дальнейшем может создать конкретную функцию, используя этот шаблон для задания прототипа, который включает имя данного шаблона. Возвращаемое функцией значение и типы параметров. - В процессе компиляции компилятор С++ будет создавать в программе функции с использованием типов, указанных в прототипах функций, которые ссылаются на имя шаблона. 3 Шаблоны функций Обычная функция Шаблон функции void swap ( int &x, int &y) template < class TYPE> { void swap (TYPE&x, TYPE&y) int temp; { TYPE temp; temp=x; temp=x; x=y; x=y; y=temp; y=temp; } } // использование шаблона или: template < typename TYPE> double x=1, y=5; swap // TYPE заменяется на double Это инстанцирование шаблона Инстанцирование – генерация функции по шаблону и ее аргументу 4 Шаблоны функций Хотя функции и классы являются мощными и гибкими инструментами для эффективного программирования, в некоторых случаях они ограничены из-за требования C++ указывать типы всех используемых параметров. Например, нужно написать функцию для вычисления наибольшего среди двух чисел: int max(int a, int b) { return (a > b) ? a : b; } Всё хорошо, пока работаем с целочисленными значениями. Если надо работать и со значениями типа double ? Можно перегрузить функцию max() для работы с типом double : double max(double a, double b) { return (a > b) ? a : b; } 5 Шаблоны функций Теперь есть две версии одной функции, которые работают с типами char, int, double и, если мы перегрузим оператор >, даже с классами. C++ требует указывать типы переменных, поэтому приходится записывать несколько версий одной и той же функции, где единственное, что меняется — это тип параметров. А это - головная боль для программистов, так как поддерживать такой код непросто как по усилиям, так и по временным затратам. И, что самое важное, это нарушает одну из концепций эффективного программирования - сократить до минимума дублирование кода. Можно написать одну версию функции max(), которая работала бы с параметрами ЛЮБОГО типа. 6 Шаблоны функций Определение слова «шаблон» в словаре: «Шаблон — это образец, по которому изготавливаются похожие изделия». Например, шаблоном является трафарет, в которой прорезан рисунок/узор/символ. Если приложить трафарет к другому объекту и распылить краску, то получим этот же рисунок, прилагая минимум усилий, быстро и, что не менее важно, мы сможем сделать десятки этих рисунков разных цветов. При этом нам нужен лишь один трафарет, не нужно определять цвет рисунка заранее (до использования трафарета). В C++ шаблоны функций — это функции, которые служат образцом для создания других подобных функций. Главная идея — создание функций без указания точного типа(ов) некоторых или всех переменных. Вместо этого мы определяем функцию, указывая тип параметра шаблона, который используется вместо любого типа данных. Создали «трафарет функции». При вызове шаблона функции, компилятор использует шаблон в качестве образца функции, заменяя тип параметра шаблона на фактический тип переменных, передаваемых в функцию. Таким образом, мы можем создать 50 «оттенков» функции, используя всего лишь один шаблон. 7 Шаблоны функций Рассмотрим ещё раз целочисленную версию функции max(): int max(int a, int b) { return (a > b) ? a : b; } Здесь мы трижды указываем тип данных: в параметрах a, b и в типе возврата функции. Для создания шаблона этой функции нам нужно заменить тип int на тип параметра шаблона функции. Поскольку в этом случае используется только один тип данных ( int ), то нам нужно указать только один тип параметра шаблона. Можно назвать этот тип как угодно, главное, чтобы это не было ключевым / зарезервированным словом. В C++ принято называть типы параметров шаблонов большой буквой T (сокращение от Type). Переделанная функция max(): T max(T a, T b) { return (a > b) ? a : b; } Но программа работать не будет, так как компилятор не знает, что такое Т 8 Шаблоны функций Нужно сообщить компилятору: - Определение шаблона функции. - То, что T является типом параметра шаблона функции. template T max(T a, T b) { return (a > b) ? a : b; } Объявление параметров шаблона: Ключевое слово template сообщает компилятору, что дальше мы будем объявлять параметры шаблона. Параметры шаблона функции указываются в угловых скобках ( < > ). Для создания типов параметров шаблона используются ключевые слова typename и class В базовых случаях использования шаблонов функций разницы между typename и class нет, можно выбрать любое из двух. При использовании ключевого слова class фактический тип параметров не обязательно должен быть классом (это может быть переменная, указатель или др.) Затем называем тип параметра шаблона (обычно T ). 9 Шаблоны функций Если требуется несколько типов параметров шаблона, то они разделяются запятыми: template // Шаблон функции здесь Если параметров несколько, то их обычно называют T1, T2 или другими буквами: T, S. Примечание: Так как тип аргумента функции, передаваемый в тип T, может быть классом, а классы, как правило, не рекомендуется передавать по значению, то лучше сделать параметры и возвращаемое значение шаблона функции константными ссылками. Например: template const T& max(const T& a, const T& b) { return (a > b) ? a : b; } 10 Использование шаблонов функций #include template const T& max(const T& a, const T& b) { return (a > b) ? a : b; } int main() { int i = max(4, 8); std::cout << i << '\n'; double d = max(7.56, 21.434); std::cout << d << '\n'; char ch = max('b', '9'); std::cout << ch << '\n'; return 0; } Использование шаблонов функций аналогично использованию обычных функций: Результат: 8 21.434 B Все три вызова функции max() имеют параметры разных типов. Так как вызываем функцию max() с тремя разными типами параметров, компилятор использует шаблон функции для создания трёх разных версий функции max() с параметрами типа: типа int (max типа double (max типа char (max Не нужно явно указывать тип передаваемых значений, компилятор вычисляет это самостоятельно. 11 Свойства параметров шаблона: - Список параметров шаблона не может быть пустым template <> - ошибка - Каждый параметр шаблона начинается словом class (typename) template - Все имена шаблона должны быть уникальными template - Разные шаблоны могут иметь одинаковые имена параметров - Все параметры шаблона обязательно должны быть использованы при определении формальных параметров функции template fun(Ax, Cy) – здесь тип В не определен при обращении - Место описания шаблона может быть до main(), после main(), но тогда с прототипом - Шаблон функции может иметь не параметризированные формальные параметры и возвращаемое значение 12 Соответствие параметров При вызове функции, определенной шаблоном, типы фактических параметров, соответствующих одинаковым параметризированным формальным параметрам, должны быть одинаковыми. Пример. Есть шаблон функции (родовая программа): 13 Соответствие параметров Главная программа: 14 продолжение 15 Специальные случаи Часто родовая программа не может работать для какого-то специального случая. Например. Написать шаблон функции поиска в двумерном массиве номера строки, где встречается первый нулевой элемент. В классическом примере для чисел любого типа эта проверка выглядит так: if matr[i][j]==0 {nom = i; flag = true;} Здесь: flag – логическая переменная, котороая показывает, был ли н вообще. В шаблоне такое действие критичное, так как для символьных переменных, для комплексных чисел эта реализация не пройдет. Для таких случаев надо использовать перегрузку функций или перегрузку операций. 16 Родовая программа 17 Главная программа 18 Пример 2 Найти номер первого элемента больше заданного числа для одномерного массива. Для проверки на пользовательском типе необходимо ввести класс complex и перегрузить там операцию > 19 Класс complex 20 Родовая функция 21 Главная программа Тесты для проверки: 22 Шаблоны функций Шаблоны функций экономят время, так как шаблон пишем только один раз, а использовать можем с разными типами данных. Шаблоны функций намного упрощают дальнейшую поддержку кода, они более безопасные, так как нет необходимости выполнять вручную перегрузку функции, копируя код и изменяя лишь типы данных, когда нужна поддержка нового типа данных. Недостатки: 1) Некоторые старые компиляторы могут не поддерживать шаблоны функций или поддерживать, но с ограничениями. Однако сейчас это уже не такая проблема, как раньше. 2) Шаблоны функций часто выдают сложные сообщения об ошибках, которые сложнее понять, чем ошибки обычных функций. 3) Шаблоны функций могут увеличить время компиляции и размер кода, так как один шаблон может быть «реализован» и перекомпилирован в нескольких файлах. Данные недостатки незначительны по сравнению с пользой и гибкостью шаблонов функций. 23 Шаблоны функций Примечание: Стандартная библиотека C++ имеет шаблон функции max() (находится в заголовочном файле algorithm ), поэтому можно не реализовывать эту функцию вручную. Если вы пишете свои собственные шаблоны функций и используете using namespace std; то не забывайте о возможности возникновения конфликтов имён, так как компилятор не сможет определить, хотите ли вы использовать свою версию функции max() или версию std::max(). 24 |