Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кетков.doc
Скачиваний:
17
Добавлен:
27.09.2019
Размер:
2.22 Mб
Скачать

14.1. Переопределение (перегрузка) функций

Программисты, работавшие на ранних версиях алгоритмического языка ФОРТРАН, недоумевали, почему в этом языке так много функций. Например:

    • sin(x) – вычисляет синус для вещественного аргумента x;

    • dsin(dx) – вычисляет синус для вещественного аргумента с удвоенной точностью;

    • csin(cx) – вычисляет синус для комплексного аргумента cx;

    • cdsin(cdx) – вычисляет синус для комплексного аргумента с удвоенной точностью.

Конечно, для каждой из этих функций в системной библиотеке существует свой алгоритм и своя программа, но разве компилятор не может определить тип аргумента и сам решить, к какой из этих программ следует обратиться. Почему бы не упростить жизнь программисту и не сказать ему – хочешь вычислить синус, так и пользуйся общепринятым в математике обозначением sin(z). А вот в зависимости от типа аргумента тебе сосчитают то, что нужно с соответствующей точностью. Эта идея была реализована в следующих версиях ФОРТРАНА и для пользователя количество математических функций "уменьшилось" почти в 4 раза.

В языке C наблюдается примерно такая же картина, как и в ранних версиях ФОРТРАНА. Представьте себе, что мы часто используем в программе форматный вывод числовых скалярных величин разного типа. Было бы удобно выделить такие операции в отдельные функции. И вот как это могло выглядеть на языке C:

void print_int(char *nx,int x)

{ printf("\n%s=%d",nx,x); }

void print_float(char *nx,float x)

{ printf("\n%s=%f",nx,x); }

void print_double(char *nx,double x)

{ printf("\n%s=%lf",nx,x); }

А в языке C++ эти же процедуры могли выглядеть так:

void print (char *nx,int x)

{ printf("\n%s=%d",nx,x); }

void print (char *nx,float x)

{ printf("\n%s=%f",nx,x); }

void print (char *nx,double x)

{ printf("\n%s=%lf",nx,x); }

Т.е. язык C++ позволяет написать несколько функций с одинаковыми именами, но они должны отличаться чем-то друг от друга. Например, по типам своих аргументов, по их количеству, по типу возвращаемого значения. Следует отметить, что две перегружаемые функции не могут отличаться только типом возвращаемого значения – в этом случае у компилятора нет никаких оснований для выбора нужной функции.

14.2. Шаблоны функций

На языке C довольно часто приходится писать стереотипные функции, которые работают по одному и тому же алгоритму, обрабатывая данные разного типа. Типичные примеры – функция swap, меняющая местами значения своих аргументов, функции сортировки числовых или строковых массивов и т.п.

В языке C++ предусмотрена возможность написания единственной функции, у которой типу обрабатываемых данных присвоено условное обозначение. Это – так называемый шаблон функции. Компилятор, просматривая фактические вызовы такой функции, определяет, с какими типами данных она должна работать, и сам размножает нашу "безтиповую" функцию в те ее модификации, которые понадобятся программе.

Для написания шаблона функции ее заголовку предшествует следующая конструкция:

template <class Type>

Здесь template – служебное слово (от англ. – шаблон);

class – служебное слово (от англ. – класс). На наш взгляд, не самый удачный термин по смыслу. Позднее в C++ появилась более разумная замена: typename – имя типа. Однако версия BC 3.1 с этим термином еще не знакома;

Type – уникальный идентификатор, придумываемый программистом для условного обозначения типа обрабатываемых данных.

И в заголовке функции, и в ее теле идентификатором Type можно пользоваться для описания типа параметров и локальных переменных:

template <class Type> void swap(Type &x,Type &y)

{ Type tmp=x; x=y; y=tmp; }

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

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

В строке шаблона может быть указан не обязательно только один условный тип данных:

template <class Type1, class Type2, class Type3)...