Попробуйте часть кода до слова main заменить на #include "stdafx.h" //1 #include <iostream> //2 using namespace std; //3 |
Функции. Новые возможности в C++
13.1. Переопределение (перегрузка) функций
Программисты, работавшие на ранних версиях алгоритмического языка ФОРТРАН, недоумевали, почему в этом языке так много функций. Например:
- sin(x) – вычисляет синус для вещественного аргумента x ;
- dsin(dx) – вычисляет синус для вещественного аргумента с удвоенной точностью;
- csin(cx) – вычисляет синус для комплексного аргумента cx ;
- cdsin(cdx) – вычисляет синус для комплексного аргумента с удвоенной точностью.
Конечно, для каждой из этих функций в системной библиотеке существует свой алгоритм и своя программа, но разве компилятор не может определить тип аргумента и сам решить, к какой из этих программ следует обратиться. Почему бы не упростить жизнь программисту и не сказать ему – хочешь вычислить синус, так и пользуйся общепринятым в математике обозначением sin(x). А вот в зависимости от типа аргумента тебе сосчитают то, что нужно с соответствующей точностью. Эта идея была реализована в следующих версиях ФОРТРАНА и для пользователя количество математических функций "уменьшилось" почти в 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++ позволяет написать несколько функций с одинаковыми именами, но они должны отличаться чем-то друг от друга. Например, по типам своих аргументов, по их количеству, по типу возвращаемого значения. Следует отметить, что две перегружаемые функции не могут отличаться только типом возвращаемого значения – в этом случае у компилятора нет никаких оснований для выбора нужной функции.
13.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>...