Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Передача параметров по имени и по значению
Когда происходит обращение к подпрограмме, переменным, указанным в списке параметров в описании (формальные параметры), присваиваются значения, ука- занные в списке параметров в момент вызова (фактические параметры), после чего 5 О Урок 1. Язык Delphi (Object Pascal] и его использование выполняются необходимые вычисления. Это называется передачей параметров по значению: в подпрограмму передаются значения нужных типов. Формальные пере- менные играют роль локальных переменных. В списке параметров перед любой переменной разрешается указывать ключевое слово var. Тогда считается, что данный параметр будет передаваться по имени: то есть копирования значения не происходит, а вместо формального параметра под- ставляется имя переменной— фактического параметра. (Отсюда следует, что в качестве фактических параметров, подставляемых вместо формальных параметров с ключевым словом var, можно применять только имена переменных.) Например: procedure MyProc(X: Byte; var Y: Byte); Параметр X будет передаваться по значению, параметр Y — по имени. При вызове МуРгос(2+2, N); операторы в теле процедуры MyProc будут обрабатывать локальную переменную X, имеющую значение 4 (2+2), и переменную Y, которая на самом деле является пере- менной N из другой части программы. На ≪физическом≫ уровне произойдет просто подстановка адреса переменной N. Использование слова var в списке параметров по способу действия аналогично использованию указателя. При этом, если в теле процедуры значение переменной X будет меняться, то по окончании работы MyProc эта локальная переменная будет удалена из памяти (до следующего вызова процедуры), а вот если произойдет изменение значения пере- менной Y, то изменится и значение переменной N. Это потенциально чревато ошибками, так как разработчик может не рассчитывать на то. что во время работы подпрограммы произойдет изменение значения одного из ее парамегров. В данном случае переменная Y является не чем иным, как указателем на переменную N, только описан он немного иначе: не с помощью опера- ции Л, а как обычная переменная. Следует избегать передачи параметров по имени за исключением случая, когда тре- буется передать в подпрограмму данные большого объема. Например, если описан тип'
type TBigArray = array [1..100000] of string[50]; то передавать переменную этого типа по значению очень неэффективно, особенно если вызов подпрограммы происходит часто, потому что при этом требуется копи- ровать большие объемы данных. То есть описание procedure Sum(A: TBigArray); неудачно в плане эффективности (хотя компилятор может самостоятельно выпол- нить передачу параметра по имени в процессе автоматической оптимизации кода). Правильнее написать так: procedure Sum(var A: TBigArray); При этом надо проследить, чтобы изменения элементов массива А внутри проце- дуры Sum не происходило (если этого не требует логика ее работы). Подпрограммы 57 Параметры-константы Если некоторый параметр будет использоваться в теле подпрограммы только для считывания данных (фактически, как константа), лучше не рассчитывать на воз- можности компилятора, а подсказать ему об этом явно. В этом случае присваива- ние данному параметру нового значения станет недопустимым. Подобная ≪подсказка≫ осуществляется указанием зарезервированного слова const в списке параметров, что позволяет организовать эффективную обработку соот- ветствующего параметра, не беспокоясь о возможных изменениях его значения. procedure Sum(const A; TBigArray),- Менять значение элементов переменной А в теле процедуры Sum теперь нельзя: компилятор сообщит об ошибке. Параметры-результаты В Паскале имеется еще одна возможность передачи параметра по имени — с помо- щью зарезервированного слова out. Такой параметр может использоваться внутри тела подпрограммы только для присваивания значения (но не для считывания дан- ных). По смыслу использование слова out противоположно использованию слова Const. Если заголовок процедуры описан так: procedure Sum(out A: TBigArray); то в теле процедуры Sum можно указывать операторы присваивания А[10000]:= 'rmml72855'; но нельзя считывать значения элементов массива А: х:= А [ 2 ] * 2; // нельзя! ПОДСКАЗКА Для получения результатов от подпрограммы всегда правильнее использовать функции. Процедуры, возвращающие результат через свои параметры, лучше применять только тогда, когда без этого не обойтись (например, параметры-результаты требуются
при создании приложений СОМ и CORBA), Преобразования сложных типов Ранее рассматривалась возможность явного преобразования типов путем использо- вания названия нужного типа как функции (Byte(300)). Паскаль допускает подоб- ный способ преобразования не только для базовых, но и для любых других типов, определенных разработчиком. ЗАМЕЧАНИЕ В Паскале не делается различий между базовыми типами, исходно существующими в языке, и типами, созданными программистами. 58 ' Урок 1. Язык Delphi (Object Pascal] и его использование Потребность в этом хоть и редко, но все же возникает. Например: type T1 = аггау[1..2] of Byte; var Al: Tl; A2: array[1..2] of Byte; Переменные _____Al и. A2 относятся к рачным типам, хотя физически (в оперативной памяти) они представлены одииаково. Поэтому переменную А2, обычный массив, можно преобразовать (привести) к типу Т1: Т1(А2) Такая запись аналогична простому обращению к имени массива А2, только при этом считается, что он имеет новый тип Tl. К элементам массива нового типа можно обращаться, как и раньше, с помощью квадратных скобок: Т1(А2)[1] Параметры без типов Паскаль позволяет указывать в заголовке подпрограммы параметры без типов (но с предшествующим словом const, var или out). procedure Surn(const A); Переменная А в таком случае считается не имеющей никакого типа, и ее нельзя использовать ни в каких выражениях или операторах, не выполнив предварительно преобразование — приведение к нужному типу. Например, в теле процедуры Sum переменную А можно использовать так: X:= Т1 (А) [5] * 2,- - Передача строк фиксированной длины Строки можно описывать, как уже говорилось ранее, двумя способами: просто как тип string, или как тип string с конкретной длиной строки в квадратных скобках. Однако указывать строки фиксированной длины в качестве параметров подпро- грамм нельзя. Их сначала надо описать как новый тип. procedure Sum(S: string[50]); // неверно! Правильно написать так: type stringSO = string[50]; procedure Sum(S: stringSO }; Передача массивов в качестве параметров Стандартный прием Паскаля состоит в описании массива как типа данных и ука- зании этого типа для параметра подпрограммы. Однако таким способом удается обрабатывать только динамические массивы и статические массивы заранее задан- ной длины. Часто требуется, чтобы подпрограмма не ограничивалась конкретными размерами массива. Например, функция, вычисляющая сумму всех элементов мас- сива, должна уметь получать в качестве параметра массив любой длины. Динами- Подпрограммы 59 ческие массивы использовать не всегда удобно и не всегда правильно, так как они ухудшают эффективность работы программы. В Паскале разрешается указывать в качестве параметров массив с неопределенными границами. procedure Sum(A: array of Byte); ВНИМАНИЕ Данное описание похоже но описание динамического массива, но не является токовым. Это просто форма записи параметра подпро- граммы для передачи статического массива заранее не известной длины. Теперь массив, описанный как var Ar: array [1..25] of Byte; можно без проблем передавать в процедуру Sum: Sum(Ar]; При этом внутри тела подпрограммы действуют следующие правила: О Нумерация элементов массива начинается с нуля (число элементов можно определить с помощью стандартной функции SizeOf); О Функция High возвращает верхнюю границу массива (равную SizeOf()-l);
О Копирование массива одним оператором присваивания не разрешается; О Вместо массива в подпрограмму может быть передана обычная переменная соответствующего типа. Внутри подпрограммы она будет представлена в виде массива из одного элемента (с индексом 0). Передача значений как массива Вместо указания в параметрах при обращении к подпрограмме имени переменной- массива можно указать непосредственно содержимое этого массива: список значе- ний через запятую в квадратных скобках. Sum([1, 5, X, а+Ь'2]); Передача массива вариантного типа - Массив, описанный как array [L.MaxNum] of Variant; может быть передан в качестве параметра в подпро]рамму, если этот параметр опи- сан как array of const: procedure Sum(A; array of const }; Внутри тела подпрограммы надо анализировать перед обработкой тип каждого эле- мента этого массива. 60 Урок 1. Язык Delphi [Object Pascal) и его использование Способы вызова подпрограмм •Подпрограммы с точки зрения прикладного программиста вызываются всегда оди- наково, но машинный код, который создается компилятором, для разных подпро- грамм может отличаться. Это зависит от целей применения конкретной подпро- граммы. Она может использоваться: О в рамках разрабатываемой прикладной программы; О как функция, доступная из динамической библиотеки.DLL; О как процедура, вызываемая из внешних программ или из Windows и т. д. Для каждого из таких нестандартных случаев вслед за заголовком подпрограммы (за точкой с запятой) должно следовать одно из ключевых слов. Таблица 1.10. Ключевые слова в заголовке подпрограмм Ключевое слово Способ передачи параметров pascal Стандартный (параметры помещаются в стек) register Способ, применяемый по умолчанию. Аналогичен использованию ключевого слова pascal, но параметры передаются с помощью трех регистров процессора, а не помещаются в стек (область оперативной памяти), что обычно приводит к повышению быстродействия программы cdecL В соответствии с соглашениями компиляторов для языков программирования С и C++. Применяется, когда происходит обращение к динамическим библиотекам DLL, написанным на этих языках stdcall В соответствии с соглашениями Windows safecall Используется при работе с компонентными технологиями При использовании ключевых слов register и pascal вычисление параметров выпол- няется слева направо и располагаются они в оперативной памяти перед вызовом
подпрограммы в таком же порядке. При использовании ключевых слов cdecL, stdcall и safecall параметры располагаются в обратном порядке (справа налево). procedure Sum(A: array of const ); stdcall; Существует еще одно зарезервированное слово Паскаля, forward, которое, при ука- зании вслед за заголовком, говорит компилятору о том, что в данном месте распо- ложен только заголовок подпрограммы, а все ее описание находится в исходном тексте далее. Такое описание обычно применяют, если в тексте имеется несколько подпрограмм, которые вызывают друг друга по кругу. Например, из процедуры Р1 вызывается процедура Р2, а из процедуры Р2 — процедура Р1. Паскаль требует, чтобы любой идентификатор, будь то переменная или подпро- грамма, был предваритачьно, до первого своего использования, описан. В таком кру- говом процессе (пример условный, потому что приведенная схема может приве- сти к бесконечной цепочке вызовов) процедура Р2, вызываемая в теле процедуры Р1, расположенной выше в исходном тексте, еще не описана, следовательно, обращаться к ней нельзя и компилятор сообщит, что обнаружен неопределенный идентифи- катор. Подпрограммы 61 Неправильно: procedure PI; Begin P2; end; procedure P2; Begin PI; end,- Правильно: procedure P2; forward; procedure PI; begin P2; end; procedure P2; Begin PI; end,- Теперь компилятор знает, как выглядит заголовок процедуры Р2, и может корректно сгенерировать машинный код для обращения к ней. '1 ПОДСКАЗКА Без таких запутанных круговых ссылок и ключевого слова forward всегда можно обойтись. Лучше не усложнять структуру программы его использованием. Перегружаемые подпрограммы Хотя в Паскале не допускается использование одинаковых названий для пере- менных, констант и других идентификаторов, для локальных переменных и под- программ делается исключение. Так как в Паскале предъявляются строгие требова- ния к типам данных, обращаться к подпрограмме, формальные параметры которой имеют тип Integer, с фактическими параметрами, имеющими тип Real, нельзя. Однако при решении задачи подчас бывает необходимо, чтобы подпрограмма с одним и тем же именем работала с разными типами данных. Здесь есть два способа действий: либо использовать данные типа Variant (что чре- вато ошибками преобразования, снижает общую эффективность программы и тре- бует от разработчика повышенной бдительности), либо применить перегружае- мые подпрограммы. Они отличаются от обычных подпрограмм тем, что имеют совпадающие имена, а различаются только типами аргументов. Чтобы указать ком- пилятору, что конкретная подпрограмма — перегружаемая, надо вслед за ее заго- ловком указать зарезервированное слово overload. 62 Урок 1. Язык Delphi (Object Pascalj и его использование При вызове такой подпрограммы компилятор по типам параметров автоматически определит, какую же подпрограмму конкретно надо использовать в данном месте. procedure Ovl (X: Real),- overload; begin end; procedure Ovl (X: Byte),- overload; Begin and; Ovlf 1); // вызывается процедура Ovl(X: Byte) Ovl(1.0); // вызывается процедура Ovlf X: Real)
Необходимое требование к перегружаемым процедурам состоит в том, чтобы списки параметров совпадали во всем, за исключением типов переменных. Надо особенно осторожно использовать перегружаемые подпрограммы с парамет- рами по умолчанию. Например: procedure Ovl(X: Byte; Y: Real - 1); overload; Begin . end; procedure Ovl (X: Byte),- overload; Begin end; При вызове Ovl(1) компилятор не сможет понять, какую из двух процедур ему вызывать, и сообщит об ошибке. Локальное описание Сразу за заголовком подпрограммы следует локальное описание типов, переменных и констант, локальных для данной подпрограммы и существующих только в ее грани- цах. Такое описание подчиняется обычным правилам Паскаля. В нем разрешается использовать слова type, var и const. Локальное описание может быть опущено. Вложенные подпрограммы Помимо обычных описаний, внутри подпрограммы допускается объявлять также локальные подпрограммы, к которым можно обращаться (вызывать) только из тела ≪родительской≫ подпрограммы. При этом локальная подпрограмма может свободно Подпрограммы 63 обращаться к любым локальным описаниям (переменным, типам), которые рас- положены до описания данной подпрограммы. Такая возможность полезна, когда во время кодирования подпрограмма начинает непредвиденно разрастаться. Ее приходится делить на более мелкие фрагменты, которые в то же время желательно не выносить за пределы текущей подпрограммы, чтобы иметь возможность пользоваться ранее сделанными локальными описаниями. Например: procedure Demo; type Tl = array [1..2] of Real; var D, Dl: Tl; S: Real; procedure InDemo; begin Dl:= D; S:= Dl[l] + Dl[2] end; Begin end; Уровень вложенности локальных подпрограмм неограничен. Тело подпрограммы Тело подпрограммы заключается в логические скобки begin/end. В них располага- ются только операторы и вызовы других подпрограмм. Возврат значений из функции Если описывается функция, то в ее теле надо определить, как значение будет воз- вращено в вызываемую программу. Для этого есть два способа. 1. Соответствующее значение присваивается переменной, имя которой совпадает с названием функции. function Sum(А, В: Integer): Integer; begin Sum:= A + В end; Имя функции для возврата значения разрешается указывать только в левой части оператора присваивания. 2. Соответствующее значение присваивается специальной локальной перемен- ной Result (эту переменную описывать не надо). 64 Урок 1. Язык Delphi (Object Pascal) и его использование function Sumf А, В: Integer): Integer; begin Result:= A + В end,- Вызов подпрограммы Когда в тексте программы указывается имя ранее описанной подпрограммы с фак- тическими параметрами, то выполнение основной части программы останавлива- ется и управление передается подпрограмме, до тех пор пока в ходе работы не будет достигнут ее конец (зарезервированное слово end). После этого управление пере- дается обратно в программу (или другую подпрограмму), вызывавшую данную подпрограмму. Параметры должны следовать в "строгом соогветствии с порядком их описания в заголовке подпрограммы. Типы их так же должны точно совпадать с указанными. Если параметров у подпрограммы нет, то записывается только название подпро- граммы и следующая за ней точка с запятой. Demo; Функции, возвращающие значение, могут использоваться так же, как и процедуры. Например, описанную выше функцию Sum можно вызывать так: X:= Sumf 2,2); а можно и так: Sum(2,2); Б последнем случае значение, возвращаемое функцией, просто теряется.__ 17. Процедурные типы данных.(указатель на код)
|
|||||||||
Последнее изменение этой страницы: 2017-02-21; просмотров: 252; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.141.30.162 (0.153 с.) |