Перегрузка процедур и функций
В некоторых случаях возникает необходимость в написании подпрограмм, которые выполняют одинаковые действия, но над переменными разных типов данных. Например:
procedure IncrementInteger(var Value: Integer);procedure IncrementReal(var Value: Real); |
В языке Delphi существует возможность дать двум и более процедурам (функциям) одинаковые идентификаторы при условии, что все такие процедуры (функции) отличаются списком параметров (количеством параметров или типом параметров). Такая возможность называется перегрузкой. Для указания того, что процедура (функция) перегружена, служит стандартная директива overload. С ее помощью вышеприведенный пример можно переписать следующим образом:
procedure Increment(var Value: Integer); overload; // процедура 1procedure Increment(var Value: Real); overload; // процедура 2 |
Какую именно процедуру использовать в том или ином случае компилятор будет определять на этапе компиляции программы по типам фактических аргументов, передаваемых при вызове.
Var X: Integer; Y: Real;begin X:=1; Y:=2.0; Increment(X); // Вызывается процедура 1 Increment(Y); // Вызывается процедура 2end. |
Особенности перегрузки:
1. При перегрузке процедур и функций существует особенность, связанная с целочисленными и вещественными типами данных. Допустим, имеются две процедуры:
procedure Print(X: Shortint); overload; // процедура 1procedure Print(X: Longint); overload; // процедура 2 |
Если мы попробуем вызвать процедуру Print, указав в качестве фактического аргумента целочисленную константу, то увидим, что выбор компилятором варианта процедуры зависит от значения константы.
Print(5); // Вызывается процедура 1Print(150); // Вызывается процедура 2Print(-500); // Вызывается процедура 2Print(-1); // Вызывается процедура 1 |
Очевидно, что одно и то же число может интерпретироваться и как Longint, и как Shortint (например, числа 5 и –1). Логика компилятора в таких случаях такова: если значение фактического параметра попадает в диапазон значений нескольких типов, по которым происходит перегрузка, то компилятор выбирает процедуру (функцию), у которой тип параметра имеет меньший диапазон значений. Например, вызов Print(5) будет означать вызов того варианта процедуры, который имеет тип параметра Shortint. А вот вызов Print(150) будет означать вызов того варианта процедуры, который имеет тип параметра Longint, т.к. число 150 не вмещается в диапазон значений типа данных Shortint.
2. Поскольку в нынешней версии среды Delphi обощенный тип данных Integer совпадает с фундаментальным типом данных Longint, следующий вариант перегрузки является ошибочным:
procedure Print(X: Integer); overload;procedure Print(X: Longint); overload; // Ошибка! |
3. Такая же ошибка возникает при использовании пользовательских типов данных, определенных через общий базовый тип.
Type TMyInteger = Integer; procedure Print(X: Integer); overload;procedure Print(X: TMyInteger); overload; // Ошибка! |
Что делать в тех случаях, когда такая перегрузка просто необходима? Для этого пользовательский тип данных необходимо создавать с использованием ключевого слова type:
Type TMyInteger = type Integer; procedure Print(X: Integer); overload;procedure Print(X: TMyInteger); overload; // Правильно |
4. Необходимо заметить, что при использовании перегруженных процедур (функций), у которых есть параметры, имеющие значения по умолчанию, нужно быть очень внимательным, т.к. могут возникнуть ситуации, когда компилятор просто не будет знать, какую именно процедуру (функцию) вы хотите вызвать. Например:
procedure Increment(var Value: Real; Delta: Real = 1.0); overload;//процедура 1procedure Increment(var Value: Real); overload; //процедура 2 |
Вызов процедуры Increment с одним параметром вызовет неоднозначность (необходимо избегать одинаковых сигнатур подпрограмм до этих параметров):
Var X: Real;begin Increment(X, 10); // Вызывается процедура 1 Increment(X); // Ошибка! Неоднозначностьend. |
5. Запрещается также перегружать функции, которые отличаются лишь типом возвращаемого значения.
function SquareRoot(X: Integer): Single; overload;function SquareRoot(X: Integer): Double; overload; // Ошибка! |
6. Запрещается также перегружать подпрограммы, которые отличаются типом: в одном случае функция, в другом - процедура.
Дата добавления: 2016-02-09; просмотров: 1193;