Jump to content

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

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

Например, доТаск() и doTask(object o) — это перегруженные функции. Чтобы вызвать последний, объект должен быть передан в качестве параметра , тогда как первый не требует параметра и вызывается с пустым полем параметра. Распространенной ошибкой было бы присвоение значения по умолчанию объекту во второй функции, что привело бы к неоднозначной ошибке вызова , поскольку компилятор не знал бы, какой из двух методов использовать.

Другим примером является Функция Print(object o) , выполняющая различные действия в зависимости от того, печатается ли текст или фотографии. Две разные функции могут быть перегружены как Печать (text_object T); Печать(изображение_объект P) . Если мы напишем перегруженные функции печати для всех объектов, которые наша программа будет «печатать», нам никогда не придется беспокоиться о типе объекта и правильном вызове функции, вызов всегда будет: Распечатать (что-то) .

Языки, поддерживающие перегрузку

[ редактировать ]

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

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

[ редактировать ]
  • Одно и то же имя функции используется для более чем одного определения функции в определенном модуле, классе или пространстве имен.
  • Функции должны иметь разные сигнатуры типов , т.е. отличаться количеством или типами формальных параметров (как в C++) или, кроме того, типом возвращаемого значения (как в Ada). [9]

Перегрузка функций обычно связана со статически типизированными языками программирования, которые обеспечивают проверку типов при вызовах функций . Перегруженная функция — это набор различных функций, которые можно вызывать с одним и тем же именем. Для каждого конкретного вызова компилятор определяет, какую перегруженную функцию использовать, и решает это во время компиляции . Это справедливо для таких языков программирования, как Java. [10]

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

Пример: перегрузка функции в C++

#include <iostream>

int Volume(int s) {  // Volume of a cube.
  return s * s * s;
}

double Volume(double r, int h) {  // Volume of a cylinder.
  return 3.1415926 * r * r * static_cast<double>(h);
}

long Volume(long l, int b, int h) {  // Volume of a cuboid.
  return l * b * h;
}

int main() {
  std::cout << Volume(10);
  std::cout << Volume(2.5, 8);
  std::cout << Volume(100l, 75, 15);
}

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

Перегрузка конструктора

[ редактировать ]

Конструкторы , используемые для создания экземпляров объекта, также могут быть перегружены в некоторых объектно-ориентированных языках программирования . Поскольку во многих языках имя конструктора предопределено именем класса, может показаться, что конструктор может быть только один. Всякий раз, когда требуется несколько конструкторов, их следует реализовать как перегруженные функции. В C++ конструкторы по умолчанию объекта не принимают никаких параметров, создавая экземпляры членов с соответствующими значениями по умолчанию, «которые обычно равны нулю для числовых полей и пустой строке для строковых полей». [11] Например, конструктор по умолчанию для объекта счета в ресторане, написанного на C++, может установить чаевые равными 15 %:

Bill()
    : tip(0.15), // percentage
      total(0.0)
{ }

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

Bill cafe;
cafe.tip = 0.10;
cafe.total = 4.00;

Перегрузив конструктор, можно было передать подсказку и сумму в качестве параметров при создании. Это показывает перегруженный конструктор с двумя параметрами. Этот перегруженный конструктор размещается в классе так же, как и исходный конструктор, который мы использовали ранее. Какой из них будет использоваться, зависит от количества параметров, предоставленных при создании нового объекта Bill (ни одного или два):

Bill(double tip, double total)
    : tip(tip),
      total(total)
{ }

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

Bill cafe(0.10, 4.00);

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

Другой причиной перегрузки конструктора может быть принудительное применение обязательных элементов данных. В этом случае конструктор по умолчанию объявляется закрытым или защищенным (или предпочтительно удаленным, начиная с C++11 ), чтобы сделать его недоступным извне. Для приведенного выше счета итоговая сумма может быть единственным параметром конструктора, поскольку у счета нет разумного значения по умолчанию для общей суммы, тогда как значение по умолчанию составляет 0,15.

Осложнения

[ редактировать ]

Две проблемы взаимодействуют и усложняют перегрузку функций: маскирование имени (из-за области видимости ) и неявное преобразование типов .

Если функция объявлена ​​в одной области, а затем другая функция с тем же именем объявлена ​​во внутренней области, существует два естественных возможных варианта поведения перегрузки: внутреннее объявление маскирует внешнее объявление (независимо от сигнатуры) или оба внутренних объявления и внешнее объявление включены в перегрузку, причем внутреннее объявление маскирует внешнее объявление только в том случае, если подпись совпадает. Первое взято из C++: «в C++ нет перегрузки между областями действия». [12] В результате, чтобы получить набор перегрузок с функциями, объявленными в разных областях видимости, необходимо явно импортировать функции из внешней области видимости во внутреннюю, с помощью using ключевое слово.

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

Они могут сочетаться запутанным образом: например, неточное совпадение, объявленное во внутренней области, может маскировать точное совпадение, объявленное во внешней области. [12]

Например, чтобы иметь производный класс с перегруженной функцией, принимающей double или int, используя функцию, принимающую int из базового класса на C++ можно было бы написать:

class B {
 public:
  void F(int i);
};

class D : public B {
 public:
  using B::F;
  void F(double d);
};

Не удалось включить using приводит к int параметр, переданный в F в производном классе преобразуется в двойной и соответствует функции в производном классе, а не в базовом классе; Включая using приводит к перегрузке производного класса и, таким образом, соответствует функции базового класса.

Предостережения

[ редактировать ]

Если метод разработан с чрезмерным количеством перегрузок, разработчикам может быть сложно определить, какая перегрузка вызывается, просто прочитав код. Это особенно верно, если некоторые из перегруженных параметров имеют типы, унаследованные от других возможных параметров (например, «объект»). IDE может выполнить разрешение перегрузки и отобразить (или перейти к) правильную перегрузку.

Перегрузка на основе типов также может затруднить обслуживание кода, поскольку обновления кода могут случайно изменить перегрузку метода, выбранную компилятором. [13]

См. также

[ редактировать ]
  1. ^ «Clojure — Изучите Clojure — Функции» . Clojure.org . Проверено 13 июня 2023 г.
  2. ^ «Спецификация языка Котлин» . kotlinlang.org .
  3. ^ Блох 2018 , с. 238-244, §Глава 8 Пункт 52: Удалить непроверенные предупреждения.
  4. ^ «37.6. Перегрузка функций» . Документация PostgreSQL . 12 августа 2021 г. Проверено 29 августа 2021 г.
  5. ^ «Руководство и справочник пользователя по базам данных PL/SQL» . docs.oracle.com . Проверено 29 августа 2021 г.
  6. ^ «Руководство Нима» . nim-lang.org .
  7. ^ «Кристалл Документы» . Crystal-lang.org .
  8. ^ «Эмбаркадеро Дельфы» . embarcadero.com .
  9. ^ Ватт, Дэвид А.; Финдли, Уильям (1 мая 2004 г.). Концепции проектирования языков программирования . John Wiley & Sons, Inc., стр. 204–207. ISBN  978-0-470-85320-7 .
  10. ^ Блох 2018 , с. 238-244, §Глава 8, пункт 52: Используйте перегрузку разумно.
  11. ^ Чан, Джейми (2017). Изучите C# за один день и выучите его хорошо (пересмотренная ред.). п. 82. ИСБН  978-1518800276 .
  12. ^ Jump up to: а б Страуструп, Бьерн . «Почему перегрузка не работает для производных классов?» .
  13. ^ Браха, Гилад (3 сентября 2009 г.). «Системная перегрузка» . Комната 101.
  • Блох, Джошуа (2018). «Эффективная Java: Руководство по языку программирования» (третье изд.). Аддисон-Уэсли. ISBN  978-0134685991 .
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 41e78537d085a99150da6d39b5f1ff57__1722835800
URL1:https://arc.ask3.ru/arc/aa/41/57/41e78537d085a99150da6d39b5f1ff57.html
Заголовок, (Title) документа по адресу, URL1:
Function overloading - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)