HTML [44] |
Visual C++ и MFC [21] |
c++ [78] |
php [19] |
Javascript [15] |
C# [51] |
загрузки [0] |
XNA
[10]
создание игр с помощью xna
|
Главная » Статьи » c++ |
С помощью шаблонов функций языка С++ можно создать единственное общее определение функции, использующееся с различными типами данных. Давайте вспомним тему "Перегруженные функции". Для использования одной и той же функции с различными типами данных нужно определить отдельную перегруженную версию этой функции для каждого типа. Если требуется функция, возвращающая абсолютную величину значения как типа int, так и типа double, то нужно написать две перегруженные функции. Например: int Abs(int N) { return N < 0 ? -N : N; } double Abs(double N) { return N < 0. ? -N : N; } Используя шаблон языка С++, можно создать единственное определение, которое будет автоматически обрабатывать значения типа int, double или любого подходящего другого типа. Такой шаблон выглядит следующим образом: template <typename T> T Abs (T N) { return N < 0 ? -N : N; } В этом определении идентификатор T является параметром типа. Он определяет тип переменной или константы, передаваемой при вызове функции. Если программа вызывает функцию Abs и передает ей значения типа int, например, cout << "Абсолютное значение для -5 = " << Abs(-5);то компилятор автоматически создаст версию функции, в которой идентификатор T имеет тип int, и добавит в программу вызов данной версии функции. Созданная компилятором функция будет эквивалентна функции, определенной явно: int Abs (int N) { return N < 0 ? -N : N; } Аналогично, если программа вызывает функцию Abs и передает ей значение типа double, например, double D = -5.12; cout << "Абсолютное значение для D = " << Abs(D);то компилятор автоматически сгенерирует версию функции, в которой заменит параметр типа T на double, и добавит в программу вызов данной версии функции. Эта версия функции эквивалентна следующей: double Abs(double N) { return N < 0. ? -N : N; } Таким же образом компилятор создает дополнительные версии функции для каждого вызова, в котором указывается новый числовой тип данных, например, short или float. Генерация новой версии функции называется созданием экземпляра шаблона функции.
При определении шаблона функции не путатйте понятия параметр функции и параметр типа. Параметр функции - это значение, передаваемое в функцию при выполнении программы. Параметр типа, напротив, задает тип аргумента, передаваемого в функцию, и полностью обрабатывается при компиляции. Обратите внимание: в определении шаблона спецификатор typename в угловых скобках ссылается на любой тип данных, фактически передаваемых при вызове (как встроенный, так и определенный программистом). Само по себе определение шаблона не вызывает генерацию кода компилятором. Компилятор создает код функции только при ее фактическом вызове. Первый же вызов с определенным типом данных приводит к генерации компилятором кода соответствующей версии функции. Последующие вызовы с указанием тех же типов данных не сгенерируют дополнительные копии функции, а только вызовут ее первоначальную копию. Но компилятор создаст новую версию функции, если тип параметра не совпадает в точности с типом в предыдущем вызове. Например, рассмотрим случай, когда программа передает в шаблон функции параметр типа long, а компилятор генерирует соответствующую версию функции. Если затем программа передаст параметр типа int, компилятор создаст полностью новую версию функции для обработки типа int. Он не будет выполнять стандартное преобразование int в long для использования кода первой версии функции. Еще один пример шаблона функции: template <typename T> T Max (T A, T B) { return A > B ? A : B; }Этот шаблон генерирует функции, возвращающие большее из двух значений одинакового типа. Так как оба параметра определены как имеющие тип идентификатора T, в вызове функции оба передаваемых переметра должны быть только одного типа. Иначе компилятор не определит, какой тип соответствует параметру T - тип первого или второго параметра. Таким образом допустимы такие вызовы функции: cout << "Большее из 10 и 5 = " << Max(10, 5) << endl; cout << "Большее из 'A' и 'B' = " << Max('A', 'B') << endl; cout << "Большее из 3.5 и 5.1 = " << Max(3.5, 5.1) << endl;А следующий вызов является недопустимым: cout << "Большее из 10 и 5.55 = " << Max(10, 5.55); // ОШИБКА!Компилятор не преобразует второй параметр int в double для приведения типов, хотя это преобразование является стандартным. Чтобы передавать параметры различных типов, нужно определить шаблон функции. template <typename T1, typename T2> T2 Max(T1 A , T2 B) { return A > B ? A : B; }В этом шаблоне Т1 обозначает тип значения, передаваемого в качестве первого параметра, а Т2 - второго. Для такой версии шаблона следующий оператор допустим и печатает значение 5.55 cout << "Большее из 10 и 5.55 = " << Max(10, 5.55); В С++ параметр типа можно использовать в любом месте кода, в котором используется имя типа. Так как возвращаемое значение преобразуется к типу второго параметра, то при изменении порядка параметров предыдущего примера cout << "Большее из 5.55 и 10 = " << Max(5.55, 10);результат сравнения будет округлен и равняться 5. Каждый параметр типа, встречающийся внутри символов "<" и ">", должен также появляться в списке параметров функции. Т.е. следующее определение шаблона функции недопустимо: template <typename T1, typename T2> T1 Max(T1 A , T1 B) { return A > B ? A : B; } // ОШИБКА! список параметров должен включать T2 как параметр типа.При таком определении компилятор, встретив вызов функции, не сможет определить значение идентификатора T2. Это - ошибка, даже если идентификатор T2 не использован. Переопределение шаблонов функцийКаждая версия функции, генерируемая с помощью шаблона, содержит одинаковый базовый код. Единственным изменяемым свойством функции будут значение параметра (или параметров) типа. Однако для отдельного параметра (или параметров) типа можно обеспечить специальную обработку. Для этого определяется обычная функция языка С++ с тем же именем, что и шаблон функции, но использующая уже имеющиеся типы данных, а не параметры типов. Обычная функция переопределяет шаблон. Т.е., если компилятор обнаруживает, что типы переданных параметров соответствуют спецификации обычной функции, то он вызовет ее, а не создаст функцию по шаблону. | |||
Просмотров: 3428 | Рейтинг: 5.0/2 |
Всего комментариев: 0 | |