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

Содержание

Слайд 2

ФУНКЦИИ Перегрузка функций. Шаблоны функций. Функция main().

ФУНКЦИИ

Перегрузка функций.
Шаблоны функций.
Функция main().

Слайд 3

Использование нескольких функций с одним и тем же именем, но с

Использование нескольких функций с одним и тем же именем, но с

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

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

Слайд 4

ПЕРЕГРУЗКА ФУНКЦИЙ. Часто бывает удобно, чтобы функции, реализующие один и тот

ПЕРЕГРУЗКА ФУНКЦИЙ.

Часто бывает удобно, чтобы функции, реализующие один и тот же

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

ПЕРЕГРУЗКА ФУНКЦИЙ. Компилятор определяет, какую именно функцию требуется вызвать, по типу

ПЕРЕГРУЗКА ФУНКЦИЙ.

Компилятор определяет, какую именно функцию требуется вызвать, по типу фактических

параметров.
Этот процесс называется разрешением перегрузки (перевод английского слова resolution в смысле «уточнение»).
Тип возвращаемого функцией значения в разрешении не участвует.

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

Слайд 6

Перегрузка функций. Допустим, имеется четыре варианта функции, определяющей наибольшее значение: int

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

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

int max(int, int);

// Возвращает наибольшее из двух целых
char* max(char*, char*); /* Возвращает подстроку наибольшей длины */
int max (int, char*); /* Возвращает наибольшее из первого параметра и длины второго */
int max (char*, int); /* Возвращает наибольшее из второго параметра и длины первого */
void f(int a, int b, char* c, char* d){
cout << max (a, b) << max(c, d) << max(a, c) << max(c, b);
}
Слайд 7

ПЕРЕГРУЗКА ФУНКЦИЙ. При вызове функции max компилятор выбирает соответствующий типу фактических

ПЕРЕГРУЗКА ФУНКЦИЙ.

При вызове функции max компилятор выбирает соответствующий типу фактических параметров

вариант функции.
в приведенном примере будут последовательно вызваны все четыре варианта функции.
Слайд 8

Перегрузка функций. Если точного соответствия не найдено:

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

Если точного соответствия не найдено:

Слайд 9

Если соответствие на одном и том же этапе может быть получено

Если соответствие на одном и том же этапе может быть получено

более чем одним способом, вызов считается неоднозначным и выдается сообщение об ошибке.
Слайд 10

ПЕРЕГРУЗКА ФУНКЦИЙ. Неоднозначность может появиться при: преобразовании типа; использовании параметров-ссылок; использовании аргументов по умолчанию.

ПЕРЕГРУЗКА ФУНКЦИЙ.

Неоднозначность может появиться при:
преобразовании типа;
использовании параметров-ссылок;
использовании аргументов по умолчанию.

Слайд 11

Пример неоднозначности при преобразовании типа: #include float f(float i){ cout return

Пример неоднозначности при преобразовании типа:

#include
float f(float i){
cout << "function

float f(float i)" << endl;
return i;
}
double f(double i){
cout << "function double f(double i)" << endl;
return i*2;
}
int main(){
float x = 10.09;
double y = 10.09;
cout << f(x) << endl; // Вызывается f(float)
cout << f(y) << endl; // Вызывается f(double)
cout « f(10) « endl;
/*Неоднозначность - как преобразовать 10: во float или double? */
return 0;
}

Для устранения этой неоднозначности требуется явное приведение типа для константы 10.

Слайд 12

Пример неоднозначности при использовании параметров-ссылок : так как нет синтаксических различий

Пример неоднозначности при использовании параметров-ссылок :

так как нет синтаксических различий между

вызовом функции, которая получает параметр по значению, и вызовом функции, которая получает параметр по ссылке.

если одна из перегружаемых функций объявлена как
int f(int a, int b),
а другая — как
int f (int a, int &b),
то компилятор не сможет узнать, какая из этих функций вызывается

Слайд 13

Пример неоднозначности при использовании аргументов по умолчанию: #include int f(int a){return

Пример неоднозначности при использовании аргументов по умолчанию:

#include
int f(int a){return a;}
int

f(int a, int b = 1){return a * b;}
int main(){
cout << f(10,2); // Вызывается f(int, int)
cout << f(10); /* Неоднозначность - что вызывается: f(int, int) или f(int) ? */
return 0;
}

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

Слайд 14

ПРАВИЛА ОПИСАНИЯ ПЕРЕГРУЖЕННЫХ ФУНКЦИЙ. Перегруженные функции должны находиться в одной области

ПРАВИЛА ОПИСАНИЯ ПЕРЕГРУЖЕННЫХ ФУНКЦИЙ.

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

иначе произойдет сокрытие аналогично одинаковым именам переменных во вложенных блоках.
Перегруженные функции могут иметь параметры по умолчанию, при этом значения одного и того же параметра в разных функциях должны совпадать. В различных вариантах перегруженных функций может быть различное количество параметров по умолчанию.
Функции не могут быть перегружены, если описание их параметров отличается только модификатором const или использованием ссылки (например, int и const int или int и int&).
Слайд 15

В C++ есть мощное средство параметризации — шаблоны. Шаблоны функций

В C++ есть мощное средство параметризации — шаблоны.

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

Слайд 16

ШАБЛОНЫ ФУНКЦИЙ. Многие алгоритмы не зависят от типов данных, с которыми

ШАБЛОНЫ ФУНКЦИЙ.

Многие алгоритмы не зависят от типов данных, с которыми они

работают.
классический пример — сортировка.
Естественно, возникает желание, параметризовать алгоритм таким образом, чтобы его можно было использовать для различных типов данных.
Слайд 17

Шаблоны функций. Первое, что может прийти в голову — передать информацию

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

Первое, что может прийти в голову — передать информацию о

типе в качестве параметра

например, одним параметром в функцию передается указатель на данные, а другим — длина элемента данных в байтах

Использование дополнительного параметра означает генерацию дополнительного кода, что снижает эффективность программы

особенно при рекурсивных вызовах и вызовах во внутренних циклах

Кроме того, отсутствует возможность контроля типов

Слайд 18

Шаблоны функций. Другим решением будет написание для работы с различными типами

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

Другим решением будет написание для работы с различными типами данных

нескольких перегруженных функций

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

Слайд 19

ШАБЛОНЫ ФУНКЦИЙ. Существуют шаблоны функций и шаблоны классов. С помощью шаблона

ШАБЛОНЫ ФУНКЦИЙ.

Существуют шаблоны функций и шаблоны классов.
С помощью шаблона функции

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

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

Слайд 20

Шаблоны функций. template заголовок{ /* тело функции */ } Формат простейшей

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

template заголовок{
/* тело функции */ }

Формат простейшей

функции-шаблона:

Вместо слова Туре может использоваться произвольное имя.

В общем случае шаблон функции может содержать несколько параметров, каждый из которых может быть не только типом, но и просто переменной, например:
template void f(){ ... }

Слайд 21

Шаблоны функций. Пример: функция, сортирующая методом выбора массив из n элементов

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

Пример:

функция, сортирующая методом выбора массив из n элементов любого типа,

в виде шаблона может выглядеть так:

template
void sort_vybor(Type *b, int n){
Type а; //буферная переменная для обмена элементов
for (int i = 0; i int imin = I;
for (int j = i + 1; j if (b[j] < b[imin]) imin = j;
а = b[i]; b[i] = b[imin]; b[imin] = a;
}
}

Слайд 22

Шаблоны функций. Пример: главная функция программы, вызывающей эту функцию-шаблон, может иметь

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

Пример:

главная функция программы, вызывающей эту функцию-шаблон, может иметь вид:

#include
template

void sort_vybor(Type *b, int n);
int main(){
const int n = 20;
int i, b[n];
for (i = 0; i> b[i];
sort_vybor(b, n); // Сортировка целочисленного массива
for (i = 0; i cout << endl;
double a[] = {0.22, 117, -0.08, 0.21, 42.5};
sort_vybor(a, 5); // Сортировка массива вещественных чисел
for (i = 0; i<5; i++) cout << a[i] << ' ';
return 0;
}
Слайд 23

ШАБЛОНЫ ФУНКЦИЙ. Первый же вызов функции, который использует конкретный тип данных,

ШАБЛОНЫ ФУНКЦИЙ.

Первый же вызов функции, который использует конкретный тип данных, приводит

к созданию компилятором кода для соответствующей версии функции.
Этот процесс называется инстанцированием шаблона (instantiation).
Конкретный тип для инстанцирования либо определяется компилятором автоматически, исходя из типов параметров при вызове функции, либо задается явным образом.
При повторном вызове с тем же типом данных код заново не генерируется.

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

Слайд 24

Шаблоны функций. Пример: явное задание аргументов шаблона при вызове: tempiate void

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

Пример:

явное задание аргументов шаблона при вызове:

tempiate

class Z> void f(Y, Z);
void g(){
f("Vasia", 3.0);
f("Vasia". 3.0);
// Z определяется как double
f("Vasia", 3.0);
// Y определяется как char*, a Z - как double
// f("Vasia", 3.0); ошибка: Х определить невозможно
}
Слайд 25

ШАБЛОНЫ ФУНКЦИЙ. Чтобы применить функцию-шаблон к типу данных, определенному пользователем (структуре

ШАБЛОНЫ ФУНКЦИЙ.

Чтобы применить функцию-шаблон к типу данных, определенному пользователем (структуре или

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

Можно предусмотреть специальную обработку отдельных параметров и типов с помощью
специализации шаблона функции.

Слайд 26

Шаблоны функций. Допустим, мы хотим более эффективно реализовать общий алгоритм сортировки

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

Допустим, мы хотим более эффективно реализовать общий алгоритм сортировки для

целых чисел.

В этом случае можно «вручную» задать вариант шаблона функции для работы с целыми числами :

void sort_vibor (int *b, int n){
... // Тело специализированного варианта функции
}

Слайд 27

ШАБЛОНЫ ФУНКЦИЙ. Сигнатура шаблона функции включает не только ее тип и

ШАБЛОНЫ ФУНКЦИЙ.

Сигнатура шаблона функции включает не только ее тип и типы

параметров, но и фактический аргумент шаблона.

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

Слайд 28

Функция, которой передается управление после запуска программы, должна иметь имя main. Функция main()

Функция, которой передается управление после запуска программы, должна иметь имя main.

Функция

main()
Слайд 29

ФУНКЦИЯ MAIN(). Функция, main может возвращать значение в вызвавшую систему и

ФУНКЦИЯ MAIN().

Функция, main может возвращать значение в вызвавшую систему и

принимать параметры из внешнего окружения.

Возвращаемое значение должно быть целого типа.

Слайд 30

Функция main(). Стандарт предусматривает два формата функции: без параметров: тип main(){

Функция main().

Стандарт предусматривает два формата функции:

без параметров:
тип main(){ /* ... */}
с

двумя параметрами:
тип main(int argc, char* argv[]){ /* ... */}
Слайд 31

ФУНКЦИЯ MAIN(). При запуске программы параметры разделяются пробелами. Имена параметров в

ФУНКЦИЯ MAIN().

При запуске программы параметры разделяются пробелами.
Имена параметров в программе могут

быть любыми, но принято использовать argc и argv.
Первый параметр (argc) определяет количество параметров, передаваемых функции, включая имя самой программы, второй параметр (argv) является указателем на массив указателей типа char*.
Каждый элемент массива содержит указатель на отдельный параметр командной строки, хранящийся в виде С-строки, оканчивающейся нуль-символом.
Первый элемент массива (argv[0]) ссылается на полное имя запускаемого на выполнение файла, следующий (argv[l]) указывает на первый параметр, argv[2] — на второй параметр, и так далее.
Параметр argv[argc] должен быть равен 0.
Слайд 32

ФУНКЦИЯ MAIN(). Если функция main() ничего не возвращает, вызвавшая система получит

ФУНКЦИЯ MAIN().

Если функция main() ничего не возвращает, вызвавшая система получит значение,

означающее успешное завершение.
Ненулевое значение означает аварийное завершение.

Оператор возврата из main() можно опускать.