Функции. Основные принципы структурной методологии. Принцип формальности. Принцип иерархического упорядочивания, страница 19

template <class t, class t, class t>;

5.  идентификаторы параметров шаблона в прототипе не опускаются;

6.  при вызове шаблонной функции все экземпляры данного аргумента шаблона должны быть строго одного типа;

7.  список параметров шаблона функций не может быть пустым, т.к. теряется возможность параметризации, и шаблон становится обычным определением конкретной функции;

8.  определяемая с помощью шаблона функция может иметь любое количество непараметризованных формальных параметров, а также непараметризованное возвращаемое функцией значение;

9.  все параметры шаблона функций должны быть обязательно использованы в качестве формальных параметров; недостаточно их использования только для спецификации типа значения:

template <class A, class B, class C>

B func(A n, C m) {B value; …}

10.  имя параметра шаблона,  например N (template <class N>),  видимо во всем определении и скрывает другие определения того же идентификатора в области, глобальной по отношению к данному шаблону; для доступа к ним используется операция изменения области видимости:

#include <iostream.h>

int N=0;                   //глобальная переменная  N

template <class N>   //прототип шаблона

N max (N x, N y);     //идентификаторы параметров в прототипе шаблона не опускаются

void main()

{int a=12, b=42;

  max (a, b);

cout << a << “  ” << b << endl;

float z=66.3f, f=222.4f;

max (z, f);

cout << z << “  ” << f << endl;

}

template <class N>     //определение шаблона

N max (N x, N y)

    {N a = x;

cout <<   “\n N=”  <<    ++ ::N << endl;

if (a<y) a=y;

return a;

     }

Результаты работы программы:

N=1

12  42

N=2

66.3  222.4

Заметим, что перегрузкой не надо злоупотреблять. Количество экземпляров шаблонной функции в памяти резко возрастает с ростом числа аргументов шаблона. Уже два аргумента в сочетании с шестью базовыми типами приводят к созданию в памяти 36 копий функции. Функции бывают довольно большими, и могут возникнуть проблемы с тем, что программе требуется слишком много памяти.

Перегрузка применима для функций, которые выполняют одни и те же действия, но с различными типами данных. Часто такого же результата можно добиться, используя вместо перегрузки функцию с аргументами по умолчанию.

С другой стороны, не всегда получается при перегрузке использовать один и тот же алгоритм (например, обмен значений двух переменных и обмен значений двух одномерных массивов). В таком случае возможна перегрузка шаблона.

Могут быть шаблоны с одинаковыми именами, но с разными параметрами. С помощью шаблона может создаваться функция с таким же именем, что и явно определенная. Распознавание идет по сигнатуре.

Рассмотрим перегрузку шаблона семейства функций на примере обмена значений двух переменных и обмена значений двух одномерных массивов:

#include <iostream.h>

template <class Any>    // прототип исходного шаблона, использующего обобщенный тип Any

void swap (Any &a, Any &b);

template <class Any>    //прототип нового шаблона

void swap (Any *a, Any *b, int n);

void show (int a[], int n);       //прототип функции show

const int Lim=8;

int main()

{int i=10, j=20;

cout << “  i=” << i <<”   j=” << j <<”\n”;

swap (i, j);                 //соответствует исходному шаблону

cout << “ new i=” << i <<”   new j=” << j <<”\n”;

int d1[Lim] = {0, 7, 0, 4, 1, 7, 7, 6};       //определение и инициализация массивов

int d2[Lim] = {0, 6, 2, 0, 1, 9, 6, 9};

cout << “ original arrays:\n”;

show(d1, Lim); show(d2, Lim);

swap(d1, d2, Lim);        //соответствует новому шаблону             

cout << “ swapped arrays:\n”;

show(d1, Lim); show(d2, Lim);

return 0;

}

template <class Any>         //исходный шаблон