Перегрузка имен функций

Как правило, давать разным функциям разные имена - мысль хорошая, но когда некоторые функции выполняют одинаковую работу над объектами разных типов, может быть более удобно дать им одно и то же имя. Использование одного имени для различных действий над различными типами называется перегрузкой (overloading). Допускается перегружать как операторы, так и функции. Так, например, у сложения существует только одно имя, +, но его можно применять для сложения значений целых, плавающих и указательных типов. Эта идея легко расширяется на обработку операций, определенных пользователем, то есть, функций. Это значит, что имя может использоваться более чем для одной функции.

Например:

void vvod(int); void vvod(char*);

Что касается компилятора, единственное общее, что имеют функции с одинаковым именем, это имя. Предположительно, они в каком-то смысле похожи, но в этом язык ни стесняет программиста, ни помогает ему. Таким образом, перегруженные имена функций - это главным образом удобство записи. Это удобство значительно в случае функций с общепринятыми именами вроде sqrt, print и open. Когда имя семантически значимо, как это имеет место для операций вроде +, * и << и в случае конструкторов, это удобство становится существенным. Когда вызывается перегруженная функция f(), компилятор должен понять, к какой из функций с именем f следует обратиться. Это делается путем сравнения типов фактических параметров с типами формальных параметров всех функций с именем f. Поиск функции, которую надо вызвать, осуществляется за три отдельных шага:

1. Искать функцию соответствующую точно, и использовать ее, если она найдена.

2. Искать соответствующую функцию, используя встроенные преобразования, и использовать любую найденную функцию.

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

Например:

print(double), print(int); void f(); { print(1); print(1.0); }

Правило точного соответствия гарантирует, что f напечатает 1 как целое и 1.0 как число с плавающей точкой. Ноль, char или short точно соответствуют параметру. Аналогично, float точно соответствует double.

К параметрам функций с перегруженными именами стандартные С++ правила неявного преобразования типа применяются не полностью. Преобразования, которые могут уничтожить информацию, не выполняются. Остаются int в long, int в double, ноль в long, ноль в double и преобразования указателей: преобразование ноль в указатель void*, и указатель на производный класс в указатель на базовый класс.

Вот пример, в котором преобразование необходимо:

print(double), print(long); void f(int a); { print(a); }

Здесь a может быть напечатано или как double, или как long. Неоднозначность разрешается явным преобразованием типа (или print(long(a)) или print(double(a))).

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

Пример:

//недопустимая перегрузка

int sum(int a){return(a+a);}

int sum(int &a){return(a+a);}//аргументы имеют одинаковый тип

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

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

Пример:

//допустимая перегрузка

int sum(int a){return(a+a);}

int sum(char a){return(int)a;}

Пример:

//допустимая перегрузка

int sum(int a);

float sum(int a);

Допускается перегружать стандартные функции. Пример: #include<stdio.h>void printf(int a){printf("%d",a);};void printf(char a){printf("%c",a);};void main(){printf(1);printf('f');}

Пример:

#include<stdio.h>#include<math.h>void sqrt(int a){printf("%d\n",a);};void sqrt(char a){printf("%c\n",a);};void sqrt(float a){printf("%f\n",a);};//недопустимо описать void sqrt(double a){printf("%f\n",a);};, т.к.//void sqrt(double);уже существует в библиотеке math.h(является стандартной)void main(){sqrt(1);sqrt(11.0f);//вызов функции пользователяsqrt(11.0);//вызов стандартной функции вычисления корня квадратногоsqrt('f');}

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: