Здавалка
Главная | Обратная связь

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



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

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

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

#include <iostream>using namespace std; long max_element(int n, int array[]) // Функция для массивов с элементами типа int.{ int value = array[0]; for (int i = 1; i < n; i++) value = value > array [i] ? value : array [i] ; cout << "\nFor (int) : "; return long(value);} long max_element(int n, long array[]) // Функция для массивов с элементами типа long.{ long value = array[0]; for (int i = 1; i < n; i++) value = value > array[i] ? value : array[i]; cout << "\nFor (long) : "; return value;} double max_element(int n, float array[]) // Функция для массивов с элементами типа float.{ float value = array[0]; for (int i = 1; i < n; i++) value = value > array[i] ? value : array[i]; cout << "\nFor (float) : "; return double(value);} double max_element(int n, double array[]) // Функция для массивов с элементами типа double.{ double value = array[0]; for (int i = 1; i < n; i++) value = value > array[i] ? value : array[i]; cout << "\nFor (double) : "; return value;} void main(){ int x[] = { 10, 20, 30, 40, 50, 60 }; long f[] = { 12L, 44L, 5L, 22L, 37L, 30L }; float y[] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 }; double z[] = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06 }; cout << "max_elem(6,x) = " << max_element(6,x); cout << "max_elem(6,f) = " << max_element(6,f); cout << "max_elem(6,y) = " << max_element(6,y); cout << "max elem(6,z) = " << max_element(6,z);}

1. В программе мы показали независимость перегруженных функций от типа возвращаемого значения. Две функции, обрабатывающие целые массивы (int, long), возвращают значение одного типа long. Две функции, обрабатывающие вещественные массивы (double, float), обе возвращают значение типа double.

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

ВНИМАНИЕ!!!

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

double multy (double x) { return x * х * х;}double multy (double x, double у) { return x * у * у;}double multy (double x, double у, double z){ return x * у * z;}

Каждое из следующих обращений к функции multy() будет однозначно идентифицировано и правильно обработано:

multy (0.4) multy (4.0, 12.3) multy (0.1, 1.2, 6.4)

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

double multy (double a = 1.0, double b = 1.0, double с = 1.0, double d = 1.0){ return a * b + c * d;}

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

multy(0.1, 1.2);

что приведет к ошибке на этапе компиляции. Будьте внимательны!!!

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

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           

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

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

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

int Abs(int N){ return N < 0 ? -N : N;} double Abs(double N){ return N < 0. ? -N : N;}

Теперь, используя шаблон мы сможем реализовать единственное описание, обрабатывающее значения любого типа:

template <typename T> T Abs (T N){ return N < 0 ? -N : N;}

Теперь - обсудим то, что у нас получилось.

1. Идентификатор T является параметром типа. Именно он определяет тип параметра, передаваемого в момент вызова функции.

2. Допустим, программа вызывает функцию Abs и передает ей значения типа int:

cout << "Result - 5 = " << Abs(-5);

3. В данном случае, компилятор автоматически создает версию функции, где вместо T подставляется тип int.

4. Теперь функция будет выглядеть так:

int Abs (int N){ return N < 0 ? -N : N;}

5. Следует отметить, что компилятор создаст версии функции для любого вызова, с любым типом данных. Такой процесс носит название - создание экземпляра шаблона функции. Или, если склоняться к более специфической терминологии - инстанционирование шаблона (template instantiation).







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.