Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 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; просмотров: 381; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.57 (0.012 с.) |