Форум программистов, компьютерный форум, киберфорум
Наши страницы

Pascal (Паскаль)

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 195, средняя оценка - 4.72
HighPredator
5544 / 1857 / 346
Регистрация: 10.12.2010
Сообщений: 5,479
Записей в блоге: 2
#1

Подключаемые модули - Pascal

15.11.2012, 20:57. Просмотров 30562. Ответов 1

Подключаемые модули.

1. Основные положения

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


2. Общая структура подключаемого модуля
Pascal
1
2
3
4
5
6
7
Unit <имя модуля>;
 
Interface
 
Implementation
 
End.
Структурно в подключаемом модуле можно выделить три раздела:
1) Интерфейсный раздел – interface (должен быть объявлен, может быть пустым)
2) Раздел реализаций – implementation (должен быть объявлен, может быть пустым)
3) Тело модуля – begin-end. (может отсутствовать)


2.1. Интерфейсный раздел.

Интерфейсный раздел – область подключаемого модуля, начинающаяся с ключевого слова interface и заканчивающаяся ключевым словом implementation, которая может содержать:
- список подключаемых модулей;
- константы;
- пользовательские типы данных;
- переменные;
- прототипы процедур и функций,
доступные из места подключения данного модуля.

Замечание 1: переменные, объявленные в разделе интерфейсов, являются глобальными. То есть существуют в любом месте программы, где подключен данный модуль, в том числе в разделе реализации самого модуля.
Замечание 2: как и в программе, вышеперечисленные секции (объявления констант, переменных и др., за исключением секции uses) в данном разделе могут быть расположены в любой последовательности и в любом количестве.
Замечание 3: если в данном разделе объявляются прототипы процедур/функций, то их реализации должны гарантированно присутствовать в разделе implementation.

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

Пример интерфейсного раздела:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Interface
 
{подключаемые модули}
Uses
  AnotherUnit;
 
{константы}
Const
  PI=3.14159265;
  E=2.71828182;
 
{пользовательские типы данных}
Type
  TMyType=array[-3..7] of real;
 
{переменные}
Var
  temp:TMyType;
 
{процедуры и функции}
Procedure Fill(var x:TMyType);
Function Find(const x:TMyType; const Value:real):Boolean;
 
Implementation
2.2. Раздел реализаций.

Раздел реализаций – область подключаемого модуля, начинающаяся с ключевого слова implementation и заканчивающаяся телом модуля (если таковое имеется) или ключевым словом end с точкой, означающим конец модуля, в которой располагаются реализации процедур и функций, объявленных в интерфейсном разделе, которая может содержать:
- список подключаемых модулей;
- константы;
- пользовательские типы данных;
- переменные;
- процедуры и функции,
необходимые для реализации процедур/функций, объявленных в интерфейсном разделе.

Основное назначение: реализация процедур и функций, описанных в секции interface.

Замечание 1: при реализации процедур и функций, описанных в интерфейсной секции, их заголовки могут быть описаны в сокращенной форме. Исключение - PascalABC: при использовании переменных заголовка в тексте реализации возникает ошибка компиляции.

Пример 1 (заголовки в сокращенной форме):
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Unit DemoUnit;
 
Interface
 
{прототип процедуры}
Procedure Swap(var a,b:integer);
 
Implementation
 
{реализация процедуры}
Procedure Swap;
Var
  Temp:integer;
Begin
  Temp:=a;
  a:=b;
  b:=Temp;
end;
 
end.
Пример 2 (заголовки в полной форме):
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Unit DemoUnit;
 
interface
 
{прототип функции}
Function GetMax(a,b:integer):integer;
 
Implementation
 
{реализация функции}
Function GetMax(a,b:integer):integer;
Begin
  If a>b then GetMax:=a
  Else GetMax:=b;
End;
 
End.
2.3. Тело модуля.

Тело модуля – последняя область подключаемого модуля, образуемая парой ключевых слов: «begin» и «end.», в которой можно размещать программный код аналогично главной программе.
Тело модуля может отсутствовать. В таком случае ключевое слово «begin» не пишется, а «end.» сигнализирует о конце модуля.

Основное назначение: инициализация переменных модуля, выделение ресурсов, необходимых для его работы и т.д.

Пример модуля, содержащего тело:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Unit DemoUnit;
 
Interface
 
Const
  N=50;
 
Var
  Roots:array[1..N] of real;
 
Implementation
 
Uses
  Math;
 
Var
  I:integer;
 
{тело модуля}
Begin
  For i:=1 to N do Roots[i]:=sqrt(i);
End.
Пример модуля без тела: (см. пример модуля для заголовков в полной форме).

Замечание 1: Программный код, размещенный в теле модуля, выполняется один раз – при загрузке модуля, до начала исполнения кода главной программы.

Замечание 2: В случае, когда в секции uses подключено несколько модулей, имеющих разделы инициализации, выполнение кода этих разделов идет в порядке подключения модулей.


2.4. Дополнительные разделы в структуре модуля.

Компиляторы Free Pascal, Pascal ABC, Pascal ABC.Net допускают помимо перечисленных выше еще два раздела:
- раздел инициализации
- раздел финализации.

2.4.1. Раздел инициализации.

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

2.4.2. Раздел финализации.

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

Основное назначение: освобождение ресурсов, выделенных для работы модуля.

Пример:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
unit DemoUnit;
 
interface
 
var
  a:array[1..20] of ^integer;{массив указателей}
 
implementation
 
{выделение памяти и инициализация значениями}
procedure AllocateArray;
var
  i:integer;
begin
  for i:=1 to 20 do
  begin
    New(a[i]);
    a[i]^:=i;
  end;
end;
 
{освобождение памяти}
procedure DeallocateArray;
var
  i:integer;
begin
  for i:=1 to 20 do Dispose(a[i]);
end;
 
initialization
  AllocateArray;{инициализация - начало работы - выделяем память}
 
finalization
  DeallocateArray;{финализация - конец работы - осовобождаем память}
 
end.
Замечание 1: программный код, размещаемый в перечисленных разделах, исполняется один раз. Код разделов инициализации – до начала исполнения кода главной программы, код разделов финализации – после.

Замечание 2: при наличии в модуле любого из данных двух разделов, наличие тела модуля более не допускается.


3. Компиляция модулей.

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


3.1. Компиляция в Turbo Pascal.

Результатом компиляции подключаемого модуля в Turbo Pascal-е является *.tpu – файл (Turbo Pascal Compiled Unit), представляющий собой машинное представление данных и кода, размещенных в нем.


3.2. Компиляция в Free Pascal.

Результатом компиляции подключаемого модуля в Free Pascal-е являются два файла: *.ppu – файл, содержащий интерфейсную часть модуля, и файл *.o - объектный файл, содержащий часть реализаций. Причем последний необходим для компоновки приложения.


3.3. Компиляция в Pascal ABC.Net.

В отличие от перечисленных выше сред в Pascal ABC.Net в процессе компиляции модуля не генерируется код на машинном языке. Компилятор данной среды завершает свою работу после выполнения семантического анализа, сохраняя семантическое дерево модуля в промежуточный формат - *.pcu – файл, который в первом приближении можно считать результатом компиляции с обозначенными ограничениями.


3.4. Ускорение компиляции программ.

На этапе компоновки приложения, компоновщик собирает исполняемый модуль, принимая на вход объектные модули. Таким образом, имея уже откомпилированные подключаемые модули, компиляция программ с их использованием ускоряется, так как они уже обработаны. Данное справедливо для Turbo и Free Pascal-ей. Однако, в Pascal ABC.Net ускорение компиляции достигается только за счет того, что отсутствует необходимость проводить синтаксический и семантический анализ.

Вывод: откомпилированные версии исполняемых модулей не совместимы между различными компиляторами.
27
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.11.2012, 20:57
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Подключаемые модули (Pascal):

Компилируются ли подключаемые модули? - Pascal
Здравствуйте, у меня 2 вопроса: 1) подключаемые модули в паскале вообще компилируются? 2) как сделать так, чтоб при вводе с клавиатуры...

Модули - Pascal
Написать программу c помошью модуля, вычисляющую удвоенный квадрат площади треугольника с помощью функции. В качестве функции оформить...

Модули - Pascal
РЕализовать в виде модуля набора подпрограмм для выполнения операции над вектором: сложение. Зделайте по проще пожалуйста.

Модули - Pascal
Дана задача: Написать подпрограмму (процедуру или функцию) для вычисления суммы , когда вид функции F(x) заранее не известен. Для этого...

Модули - Pascal
помогите плиз завтро надо сдавать ваще хз как сделать... создать функции MyVal – преобразовать строку в целое число NewCopy –...

Модули - Pascal
Провести вычисления. Необходимые для вычислений функции (факториал, возведение в степень и т.д.) описать в модуле. Вот есть пример...

1
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
24023 / 16004 / 4844
Регистрация: 22.10.2011
Сообщений: 28,326
Записей в блоге: 5
18.04.2015, 12:10 #2
Существует еще несколько особенностей работы с модулями.


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

Первый модуль:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unit u1;
 
interface
 
type 
  TestType = array[1 .. 10] of integer;
  
procedure TestProc;
 
implementation
 
procedure TestProc;
begin
  writeln('TestProc from u1');
end;
 
end.
Второй модуль:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unit u2;
 
interface
 
type
  TestType = integer;
  
procedure TestProc;
 
implementation
 
procedure TestProc;
begin
  writeln('TestProc from u2');
end;
 
end.
Основная программа:
Pascal
1
2
3
4
5
uses u1, u2;
 
begin
  TestProc; { Вывод: "TestProc from u2" }
end.
При сборке программы не будет никаких проблем, несмотря на одинаковые идентификаторы, а вот при запуске отработает та процедура, которая описана в модуле u2 (поскольку он подключен позже, чем u1). Если поменять порядок подключения модулей:
Pascal
1
2
3
4
5
uses u2, u1;
 
begin
  TestProc; { Вывод: "TestProc from u1" }
end.
, и пересобрать программу, то теперь отработает TestProc из модуля u1.

Для того, чтобы использовать идентификатор из модуля, подключенного НЕ последним, нужно указать, в каком именно модуле он описан:
Pascal
1
2
3
4
5
uses u2, u1;
 
begin
  u2.TestProc; { Теперь будет  вызвана процедура из u2, независимо от порядка подключения }
end.
Но если с подобной процедурой программа хотя бы будет компилироваться, то при попытке использовать другой тип (массив вместо скалярного типа, например), будут большие проблемы:

Pascal
1
2
3
4
5
6
7
8
uses u1, u2;
 
var 
  i : integer;
  a : TestType;
begin
  for i := 1 to 10 do a[i] := i; { Ошибка, нелегальный квалификатор (Illegal Qualifier) }
end.
, хотя казалось бы, модуль подключен к программе, и все должно работать. Незнание этой особенности очень часто приводит к недоразумениям, особенно при использовании VCL/LCL или других библиотек совместно с модулем Windows. Например, как вот тут: Создать объект Bitmap для загрузки изображения
Решение - точно такое же, как и в предыдущем случае. Либо поменять местами названия модулей в списке uses, либо использовать полное имя типа:
Pascal
1
a : u1.TestType;

Еще одна особенность - подключение первого модуля ко второму, а второго - к первому. Так называемая циклическая зависимость (circular unit reference). Вот пример (он, правда, синтетический, но основная идея понятна. При работе с теми же VCL/LCL тоже довольно часто встречается подобная ошибка, когда нужно связать две формы между собой) :

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unit u1;
 
interface
uses u2;
 
procedure PrintFirst;
procedure PrintFirstSecond;
 
implementation
 
procedure PrintFirst;
begin
  writeln('Print first');
end;
procedure PrintFirstSecond;
begin
  writeln('Print first');
  PrintSecond;
end;
 
end.
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unit u2;
 
interface
uses u1;
 
procedure PrintSecond;
procedure PrintSecondFirst;
 
implementation
 
procedure PrintSecond;
begin
  writeln('Print Second');
end;
procedure PrintSecondFirst;
begin
  writeln('Print Second');
  PrintFirst;
end;
 
end.
Основная программа
Pascal
1
2
3
4
5
uses u1, u2;
 
begin
  PrintFirstSecond;
end.
Этот проект компилироваться не будет, потому что присутствует циклическая зависимости: первый модуль ссылается на второй, а второй - на первый. Для того, чтобы решить проблему, достаточно перенести раздел Uses в любом из модулей (либо в обоих) из секции Interface в секцию Implementation:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unit u1;
 
interface
 
procedure PrintFirst;
procedure PrintFirstSecond;
 
implementation
uses u2; { <--- Раньше было в Interface }
 
procedure PrintFirst;
begin
  writeln('Print first');
end;
procedure PrintFirstSecond;
begin
  writeln('Print first');
  PrintSecond;
end;
 
end.
, и проблема будет решена, программа компилируется и запускается. Когда хотя бы один из ссылающихся друг на друга модулей подключается в разделе Implementation, компилятор умеет разруливать такую зависимость.

Это связано с тем, что для возможности использования модуля компилятор должен откомпилировать его хотя бы частично, только Interface-часть, чтобы знать, какие сущности, объявленные в этом модуле, могут быть использованы извне, и если хотя бы один из модулей частично откомпилирован (в приведенном выше примере это будет u1, в его интерфейсной части теперь нет никаких недомолвок и еще неизвестных модулей), то другой также прекрасно соберется.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.04.2015, 12:10
Привет! Вот еще темы с ответами:

Модули. - Pascal
Задание в вордовском документе. Срок выполнения до субботы. Заранее большое спасибо!

модули - Pascal
Получить матрицу С путем сложения матриц A и B. Определить в результирующей матрице строку, содержащую наибольшее количество...

Модули - Pascal
Помогите!!Не врубаюсь в тему модули!Надо решить... Разработать модуль, реализующий функции калькулятора.Предусмотреть возможность...

Модули - Pascal
NewCopy – выделение строки с заданного начального символа до заданного конечного символа NewDelete – удаление подстроки с начальной...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru