Трохи раніше була розглянута тема про перегрузке функций в C++ . Вы узнали о возможности написать несколько функций с одинаковым именем, которые выполняют одинаковые задачи. Основное отличие между ними – сигнатура (типи параметрів і / або кількість параметрів). При запуске программы, компилятор сам выберет, яку з перевантажених функцій застосувати(исходя из того, що передано в функцію)
Шаблоны так же позволяют функциям обрабатывать разные типы данных, передані у вигляді параметрів. Але при цьому досить написати одне загальне визначення функції. Смотрите как это выглядит.
Визначаючи шаблон функції ми використовували зарезервовані слова C ++: template і typename. template говорит о том, что сейчас будет определен шаблон. А в кутових дужках післяtypenameдається умовне ім'я типу даних. Тут, вместо имени T, можно присвоить любое (очень желательно корректное) имя.
Далее определяется сама функция. Тип возвращаемого значения указываем T. Параметри: число типа T, и число типа int. Ця функція вважає відсоток від числа і повертає значення в програму. И число, и процент передаются как параметры. Наприклад першим параметром ми передамо в функцію ціле число (100). Під час запуску, компилятор отметит себе что T це int і замінить в шаблоні функції всі ці Tна int. Таким образом для компилятора функция примет вид:
Мы этого не увидим явно, но все отработает замечательно. Яке б число ми не передали в цю функцію першим параметром, компилятор создаст экземпляр шаблона функции для любого вызова. При этом первый параметр может иметь любой тип данных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream> using namespace std; template <typename T> T calcPercent(T number, int percent) { return number * percent / 100; } int main() { setlocale(LC_ALL, "rus"); cout << "20% от 200: " << calcPercent(200, 20) << endl; cout << "10% от 42.56: " << calcPercent(42.56, 10) << endl; return 0; } |
В итоге на экране увидим такой результат расчетов:
Говоря об определении шаблона функции, хочется добавить, що в кутові дужки після ключового слова template можливо записати кілька умовних імен для типів даних. Зачем это может понадобиться? Рассмотрим такой пример:
Необходимо написать функцию, которая примет два числа, определит максимальное из них и вернет его в программу. Будем иметь ввиду, що в функцію ми можемо передати числа різних типів. Можливий і випадок, что одно число будет целым, а второе – вещественным. Смотрите что произойдет:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> using namespace std; template <typename T> T findMax(T firstNum, T secondNum) { if (firstNum > secondNum) return firstNum; else if (secondNum > firstNum) return secondNum; else return 0; } int main() { setlocale(LC_ALL, "rus"); cout << "Сравниваем 255 и 700! Большее = " << findMax(255, 700) << endl; cout << "Сравниваем 8.5 и 4.9! Большее = " << findMax(8.5, 4.9) << endl; // при передаче 2-х параметров с разными типами возникнет ошибка cout << "Сравниваем 100 и 5.1! Большее = " << findMax(100, 5.1) << endl; return 0; } |
Первый и второй параметры функции определены, как параметры типа T. С вызовами функции в строках 19-20 проблем не возникает, так как передаваемые параметры имеют одинаковый тип данных. Проблемы возникнут в строке 22 при компіляції. И это понятно. Компилятор запутается. Он не может преобразовать тип int в double.
Чтобы обойти эту проблему, надо написать другой шаблон.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> using namespace std; template <typename T_1, typename T_2> T_2 findMax(T_1 firstNum, T_2 secondNum) { if (firstNum > secondNum) return firstNum; else if (secondNum > firstNum) return secondNum; else return 0; } int main() { setlocale(LC_ALL, "rus"); cout << "Сравниваем 255 и 700! Большее = " << findMax(255, 700) << endl; cout << "Сравниваем 8.5 и 4.9! Большее = " << findMax(8.5, 4.9) << endl; // ошибки не будет: cout << "Сравниваем 100 и 5.1! Большее = " << findMax(100, 5.1) << endl; return 0; } |
Тутtypename T_1 обозначает тип параметра, который передается в функцию первым. typename T_2 відповідно позначає тип другого параметра. Такой вариант определения шаблона функции предупредит ошибки, возникающие при передаче параметров разных типов.
Важно запомнить,что если вы в угловых скобках вы даете несколько условных имен для типов параметров функции (как в нашем примере), все эти имена типов должны быть упомянуты в сигнатуре функции. Иначе не избежать ошибки при компиляции. Например такое определение шаблона
призводить до наступних помилок:
В шаблоне мы определили условные им типов T_1 і T_2, а в сигнатурі прописали тільки типT_1 .
На практике вы можете встретить определение шаблона функции таким способом, где вместо ключевого слова typename используется слово class. Наприклад:
воно рівнозначно тому визначенню, которое мы рассматривали
Ранее, до выхода стандарта C 98, в шаблонах завжди використовували словоclass. Сейчас же лучше, коли з'явилося ключове словоtypename , лучше применять его. Так как оно более явно говорит о том, що іменаT_1 іT_2 представляють тип.
Подведем итог. Шаблон функции предназначен для создания обобщенного описания функции. Такая функция сможет принять параметры любого типа. Шаблон дозволить компілятору генерувати код функції для конкретного типу (или типов) данных, который был передан в неё при вызове.
Обов'язково подивіться відео про шаблони:
А можна зробити змінну універсальної?Тобто вона може бути типом double,а так само і int.
Вибачте, дилетант. А навіщо в коді на більше менше взагалі застосовувати шаблон? Ставимо тип значення ф-ії double або float В параметрах також ставимо або ту чи іншу і вперед. Все працює.
Якось так.
Погано і незрозуміло пояснено.
Особливо в останньому прикладі, де: “У шаблоні ми визначили умовні їм типи T_1 і T_2, а в сигнатурі прописали лише тип T_1.”
Сигнатури взагалі не видно тут і щоб, бл * дь, до чого – х-й зрозумій!
Так в останньому прикладі спеціально допущена помилка. Так в останньому прикладі спеціально допущена помилка
Так в останньому прикладі спеціально допущена помилка, Так в останньому прикладі спеціально допущена помилка.