Что такое перегрузка методов c
Перейти к содержимому

Что такое перегрузка методов c

  • автор:

Что такое перегрузка методов c

Язык С++ позволяет определять функции с одним и тем же именем, но разным набором параметров. Подобная возможность называется перегрузкой функций ( function overloading ). Компилятор же на этапе компиляции на основании параметров выберет нужный тип функции.

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

  • имеют разное количество параметров
  • соответствующие параметры имеют разный тип

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

Рассмотрим простейший пример:

#include int sum(int, int); double sum(double, double); int main() < int result1 ; // выбирается версия int sum(int, int) std::cout ; // выбирается версия double sum(double, double) std::cout int sum(int a, int b) < return a + b; >double sum(double a, double b)

Здесь определены две версии функция sum, которая складывает два числа. В одном случае она складывает два числа типа int, в другом — числа типа double. При вызове функций компилятор на основании переданных аргументов определяет, какую версию использовать. Например, при первом вызове передаются числа int:

int result1 ;

Соответственно для этого вызова выбирается версия

int sum(int, int);

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

double result2 ;

Поэтому выбирается версия, которая принимает числа double:

double sum(double, double);

Аналогично перегруженные версии функции могут отличаться по количеству параметров:

#include int sum(int, int); int sum(int, int, int); int main() < int result1 ; // выбирается версия int sum(int, int) std::cout ; // выбирается версия int sum(int, int, int) std::cout int sum(int a, int b) < return a + b; >int sum(int a, int b, int c)

Перегрузка функций и параметрами-ссылки

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

void print(int); void print(int&);

Не считаются разными версиями функции print.

Перегрузка и параметры-константы

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

void print(int); void print(const int);

Во втором прототипе компилятор игнорирует оператор const .

Пример перегрузки функции с константными параметрами

#include int square(const int*); int square(int*); int main() < const int n1; int n2; int square_n1 ; int square_n2 ; std::cout int square(const int* num) < return *num * *num ; >int square(int* num) < *num = *num * *num; // изменяем значение по адресу в указателе return *num; >

Здесь функция square принимает указатель на число и возводит его в квадрат. Но первом случае параметр представляет указатель на константу, а во втором — обычный указатель.

В первом вызове

int square_n1 ;

Компилятор будет использовать версию

int square(const int*);

так как передаваемое число n1 представляет константу. Поэтому переданное в эту функцию число n1 не изменится.

В втором вызове

int square_n2 ;

Компилятор будет использовать версию

int square(int*);

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

square(n1): 4 n1: 2 square(n2): 9 n2: 9

С передачей константной ссылки все будет аналогичо.

Перегрузка методов

В C# допускается совместное использование одного и того же имени двумя или более методами одного и того же класса, при условии, что их параметры объявляются по-разному. В этом случае говорят, что методы перегружаются, а сам процесс называется . Перегрузка методов относится к одному из способов реализации полиморфизма в C#.

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

Совершенно недостаточно, чтобы два метода отличались только типами возвращаемых значений. Они должны также отличаться типами или числом своих параметров. (Во всяком случае, типы возвращаемых значений дают недостаточно сведений компилятору C#, чтобы решить, какой именно метод следует использовать.) Разумеется, перегружаемые методы могут отличаться и типами возвращаемых значений. Когда вызывается перегружаемый метод, то выполняется тот его вариант, параметры которого соответствуют (по типу и числу) передаваемым аргументам.

Давайте рассмотрим пример использования перегрузки методов:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 < class UserInfo < // Перегружаем метод ui public void ui() < Console.WriteLine("Пустой метод\n"); >public void ui(string Name) < Console.WriteLine("Имя пользователя: ",Name); > public void ui(string Name, string Family) < Console.WriteLine("Имя пользователя: \nФамилия пользователя: ",Name,Family); > public void ui(string Name, string Family, byte Age) < Console.WriteLine("Имя пользователя: \nФамилия пользователя: \nВозраст: ", Name, Family, Age); > > class Program < static void Main(string[] args) < UserInfo user1 = new UserInfo(); // Разные реализации вызова перегружаемого метода user1.ui(); user1.ui("Ерохин", "Александр", 26); Console.ReadLine(); >> > 

Использование перегруженного метода C#

Как видите метод ui перегружается три раза. Модификаторы параметров ref и out также учитываются, когда принимается решение о перегрузке метода. Несмотря на то что модификаторы параметров ref и out учитываются, когда принимается решение о перегрузке метода, отличие между ними не столь существенно. Давайте добавим еще одну перегрузку в вышеуказанный пример:

// Используем модификатор параметров public void ui(string Name, string Family, ref byte Age)

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

Допустим, что требуется функция, определяющая абсолютное значение. В языках, не поддерживающих перегрузку методов, обычно приходится создавать три или более вариантов такой функции с несколько отличающимися, но все же разными именами. Например, в С функция abs() возвращает абсолютное значение целого числа, функция labs() — абсолютное значение длинного целого числа, а функция fabs () — абсолютное значение числа с плавающей точкой обычной (одинарной) точности.

В С перегрузка не поддерживается, и поэтому у каждой функции должно быть свое, особое имя, несмотря на то, что все упомянутые выше функции, по существу, делают одно и то же — определяют абсолютное значение. Но это принципиально усложняет положение, поскольку приходится помнить имена всех трех функций, хотя они реализованы по одному и тому же основному принципу. Подобные затруднения в C# не возникают, поскольку каждому методу, определяющему абсолютное значение, может быть присвоено одно и то же имя. И действительно, в состав библиотеки классов для среды .NET Framework входит метод Abs(), который перегружается в классе System.Math для обработки данных разных числовых типов. Компилятор C# сам определяет, какой именно вариант метода Abs() следует вызывать, исходя из типа передаваемого аргумента.

В C# определено понятие сигнатуры, обозначающее имя метода и список его параметров; Применительно к перегрузке это понятие означает, что в одном классе не должно существовать двух методов с одной и той же сигнатурой. Следует подчеркнуть, что в сигнатуру не входит тип возвращаемого значения, поскольку он не учитывается, когда компилятор C# принимает решение о перегрузке метода. В сигнатуру не входит также модификатор params.

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

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 < class Program < static void Main(string[] args) < string s = "Всем привет, это сайт professorweb.ru :)"; char ch = 'е'; string smile = ":)"; Console.WriteLine("Исходная строка: \n\n----------------------\n",s); // Первая перегрузка if (s.IndexOf(ch) != -1) Console.WriteLine("Символ '' находится на позиции ",ch,s.IndexOf(ch)); // Вторая перегрузка if (s.IndexOf(ch, s.IndexOf(ch)+1) != -1) Console.WriteLine("Далее, этот символ встречается на позиции ", s.IndexOf(ch, s.IndexOf(ch) + 1)); // Третья перегрузка if (s.IndexOf(smile, 0, s.Length) != -1) Console.WriteLine("Смайл найден на позиции ", smile, s.IndexOf(smile, 0, s.Length)); // Четвертая перегрузка if (s.IndexOf(smile, StringComparison.Ordinal) != -1) Console.WriteLine("Теперь смайл найден другим способом"); Console.ReadLine(); > > >

Перегрузки IndexOf C#

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

Урок #23 – Перегрузка методов в языке C#

Урок #23 – Перегрузка методов в языке C#

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

Видеоурок

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

Что такое перегрузка методов?

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

Отличным примером является метод «Write» или «WriteLine». В данный метод мы можем передавать различные типы данных, но при этом вывод информации происходит без каких-либо ошибок. Так происходит из-за того, что в классе Console есть множество перегрузок методов «Write» и «WriteLine».

Как создать перегрузку?

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

public static string getInfo(string some) < return some + "!"; >public static int getInfo(int a, int b)

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

Что такое перегрузка методов c

Иногда возникает необходимость создать один и тот же метод, но с разным набором параметров. И в зависимости от имеющихся параметров применять определенную версию метода. Такая возможность еще называется перегрузкой методов (method overloading).

И в языке C# мы можем создавать в классе несколько методов с одним и тем же именем, но разной сигнатурой. Что такое сигнатура? Сигнатура складывается из следующих аспектов:

  • Имя метода
  • Количество параметров
  • Типы параметров
  • Порядок параметров
  • Модификаторы параметров

Но названия параметров в сигнатуру НЕ входят. Например, возьмем следующий метод:

public int Sum(int x, int y)

У данного метода сигнатура будет выглядеть так: Sum(int, int)

И перегрузка метода как раз заключается в том, что методы имеют разную сигнатуру, в которой совпадает только название метода. То есть методы должны отличаться по:

  • Количеству параметров
  • Типу параметров
  • Порядку параметров
  • Модификаторам параметров

Например, пусть у нас есть следующий класс:

class Calculator < public void Add(int a, int b) < int result = a + b; Console.WriteLine($"Result is "); > public void Add(int a, int b, int c) < int result = a + b + c; Console.WriteLine($"Result is "); > public int Add(int a, int b, int c, int d) < int result = a + b + c + d; Console.WriteLine($"Result is "); return result; > public void Add(double a, double b) < double result = a + b; Console.WriteLine($"Result is "); > >

Здесь представлены четыре разных версии метода Add, то есть определены четыре перегрузки данного метода.

Первые три версии метода отличаются по количеству параметров. Четвертая версия совпадает с первой по количеству параметров, но отличается по их типу. При этом достаточно, чтобы хотя бы один параметр отличался по типу. Поэтому это тоже допустимая перегрузка метода Add.

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

Add(int, int) Add(int, int, int) Add(int, int, int, int) Add(double, double)

После определения перегруженных версий мы можем использовать их в программе:

Calculator calc = new Calculator(); calc.Add(1, 2); // 3 calc.Add(1, 2, 3); // 6 calc.Add(1, 2, 3, 4); // 10 calc.Add(1.4, 2.5); // 3.9
Result is 3 Result is 6 Result is 10 Result is 3.9

Также перегружаемые методы могут отличаться по используемым модификаторам. Например:

void Increment(ref int val) < val++; Console.WriteLine(val); >void Increment(int val)

В данном случае обе версии метода Increment имеют одинаковый набор параметров одинакового типа, однако в первом случае параметр имеет модификатор ref. Поэтому обе версии метода будут корректными перегрузками метода Increment.

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

int Sum(int x, int y) < return x + y; >int Sum(int number1, int number2) < return number1 + number2; >void Sum(int x, int y)

Сигнатура у всех этих методов будет совпадать:

Sum(int, int)

Поэтому данный набор методов не представляет корректные перегрузки метода Sum и работать не будет .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *