home   map   mail  
 
:: О нас :: Координаты :: Прайс-лист :: Форум :: Статьи :: Наши клиенты ::  
  rs    
 

E-Mail: support@nerusoft.com
Телефоны:
      +380 67 901-63-22
      +380 63 108-17-00
ICQ: 131-674-371
Skype: rudjuk

 
   
OTPCapital   OTPCapital - Компания
управления активами
OTP-Банк   OTP-Банк - крупнейший
банк Украины
Бухгалтерское обслуживание Факториал Консалт   Бухгалтерское,
аудиторское и
юридическое
обслуживание от
Факториал-Консалт
lightnight   Информационно-
развлекательный сайт
LightNight.
Компания РМед   Компания по продаже
медицинского
оборудования РМед.
Casa-De-Confraria   Casa-De-Confraria -
вилла в Португалии.
Н.Транс   Компания по продаже
косметики Н.Транс
Клуб SportLife   Спортивный клуб
SportLife
  Сайт
“Пригласи
Деда Мороза"
  Американская
компания
“CharlieMotors”
  Национальный
Цирк Украины
Все проекты   Все проекты >>>
 
Внимание!
Это старый наш сайт. Новый сайт находится по адресу: http://corp2.net
 
 

 Часть 5. Динамическая память. Классы и объекты.

Динамическая память и указатели


Память для переменных, объявленных в разделе var выделяется во время компиляции. Такая память называется статической. Однако, часто не известно сколько памяти нужно программе и выделяется память во время выполнения. Такая память называется динамической.

Адреса переменных можно хранить в указателях. Указатели – это ячейки памяти специального типа. Они объявляются таким образом:

var

<название переменной-указателя>:^<тип>;


^ - это указатель.


Пример объявления указателя:

var

my_int: ^integer;

my_real: ^real;


По умолчанию, все указатели имеют значение nil, что означает, что переменная никуда не указывает.

Одинаковые указатели можно присваивать друг-другу.

Для того, чтоб получить значение указателя необходимо воспользоваться операцией разыменовывания указателя (для этого знак указателя ставится после переменной).

Например:

write(my_int^); - печатает значение переменной-указателя my_int.


Для того, чтоб получить адрес переменной необходимо перед переменной написать знак @. Например:

@my_int – определение адреса переменной my_int.


Для того, чтоб работать с динамическими переменными, необходимо под неё выделить память. Для этого предназначена процедура New( ). После завершения работы с переменной необходимо освободить указатель, вызвав команду Dispose( ).


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

var

my_struct: pointer;


Для работы с такими указателями предусмотрено ряд функций [7]:

procedure GetMem(var P: Pointer; Size: Integer);

// Выделяет для указателя P память размером Size.


procedure FreeMem(var P: Pointer [; Size: Integer]);

// Освобождает память, заданную указателем.


function SizeOf(X): Integer;

// Возвращает размер памяти, выделенной для указателя


Обработка ошибок времени выполнения


В FreePascal определены две конструкции для обработки исключительных ситуаций [4]:


try

<операторы>;

finally

<операторы, которые должны выполняться в любом случае>

end;


Если возникает ошибка среди операторов между try и finally, тогда программа переходит к выполнению операторов, находящихся между finallyend;


try

<операторы>;

except

<операторы, которые выполняются при возникновении ошибки>

end;


Если возникает ошибка среди операторов между try и except, тогда программа переходит к выполнению операторов, находящихся между exceptend;


В конструкции try…except предусмотрен оператор с помощью которого можно получить точный текст и код ошибки – это оператор on..do. Такой оператор ставится только между exceptend. Пример его использования:

try

s:=m/0;

except

on E: Exception do

begin

WriteLn('Произошла ошибка:');

WriteLn(E.Message);

end

else

Raise;

end;

Оператор Raise передаёт управлению стандартному обработчику исключительных ситуаций.


Пример: Выведем результаты деления 10 на все целые цифры от -10 до 10.


Листинг программы (на компакте в папке try):


program consple_laz;

// Программа выводит результаты деления 10 всех цифр, начиная от -10 до 10


{$mode objfpc}{$H+}

{$AppType CONSOLE}


Uses SysUtils;


var i: integer;

begin


for i:=-10 to 10 do

begin

try

writeln(format('10/%d=%f',[i, 10/i])); // Выводим результат от деления

except

on E: Exception do // Если возникла ошибка, тогда выводим ошибку

begin

writeln(format('10/%d=%s',[i, E. Message]));

end;

end;

end;

readln;


end.


Прокомпилируйте программу с помощью комбинации Ctrl+F9 и запустите из exe-файл программы (для того, чтоб не выскакивали окна среды разработки при возникновении ошибки). Получите результат:


10/-10=-1,00

10/-9=-1,11

10/-8=-1,25

10/-7=-1,43

10/-6=-1,67

10/-5=-2,00

10/-4=-2,50

10/-3=-3,33

10/-2=-5,00

10/-1=-10,00

10/0=Division by zero

10/1=10,00

10/2=5,00

10/3=3,33

10/4=2,50

10/5=2,00

10/6=1,67

10/7=1,43

10/8=1,25

10/9=1,11

10/10=1,00


Структура модульных файлов Pascal


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

Модули – это программные единицы, служащие для размещения фрагментов программ.[7]


Структура модулей:


unit Test;

interface

// Глобальные объявления и переменные

implementation

// Локальные объявления и переменные


initialization

// Код, выполняемый при запуске программы

finalization

// Код завершения работы программы

end;


Раздел инициализации initialization является не обязательным. Он необходим для выполнения кода при запуске программы.


Классы и объекты


FreePascal является объектно-ориентированным языком программирования. В основе объектной модели Паскаля лежат понятия класса и объекта. [7]

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

Объект – это конкретный экземпляр класса.

В объектно-ориентированных языках есть 3 основных понятии: инкапсуляция, наследование и полиморфизм.

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

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

Полиморфизм позволяет использовать одинаковые имена для методов, входящих в различные классы.[7]


Для объявления класса используется конструкция:

type

<название класса> = class(<название класса-родителя>)

<методы и переменные класса>

private

<локальные объявления, доступные только в пределах модуля>

protected

<защищенные объявления, доступные только в классах-потомках>

public

<глобальные объявления, доступные из других модулей>

published

<свойства и методы, видимые в инспекторе объектов (для публикации)>

end;


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

Обратите внимание, что в классе предусмотрены различные области видимости объектов.

private – методны, свойства, сопытия и поля видны только в области текущего класса;

protected – то же, но в текущем объекте и объектах-потомках.

public - то же, но видно везде.

published – видно везде, а так же свойство или метод показывается в инспекторе объектов среды разработки.

Поля и свойства


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


type

TMyClass = class

FirstName: String;

SecondName: String;

Obj_Control: TObject;

end;


Для того, чтоб обратиться к классу необходимо записать названия класса и через точку название поля. Например:


var M: TMyClass;

begin

M.FirstName:='Иванов';

M.SecondName:='Иван';

M.Obj_Control:=nil;

end;


Свойства аналогично выглядят, как и поля, но в отличие от полей, свойства могут управлять доступ к полям. Для получения информации в свойстве используется зарезервированное слово Get, а для установки значения свойства – Set.

Например:

type

TMyClass = class

Constructor Create;

Destructor Destroy;

FFullName: String;

function GetFullName: String; Virtual; abstract;

property FullName: String read GetFullName write FFullName;

end;


В этом примере при вызове значения (read) свойства FullName выполняется вызов функции GetFullName, а запись (write) производися в функцию FFullName.


Если необходимо производить запись через процедуру, тогда процедура должна быть с параметром Value:<тип свойства>. Например, для случая выше можно было написать процедуру: procedure SetFullName(Value: String).

Методы


Методами называются инкапсулированные в классе процедуры и функции.[7]

Например:

type

TMyClass = class

FirstName: String;

SecondName: String;

Obj_Control: TObject;

function GetFillName: String;

end;


Обращение к методам идём по аналогии со свойствами, например:

Name:=M.GetFullName;


Различают статические, динамические и виртуальные методы.

По умолчанию, считается, что метод статический. Например:


type

TMyClass = class

function GetFillName: String;

end;

TMyUniverClass = class(TMyClass)

function GetFillName: String;

end;

var MyC: TMyClass;

MyUniver: TMyUniverClass;


begin

WriteLn(MyC.GetFillName);

WriteLn(MyUniver.GetFillName);

end;


В данном случае, компилятор просто заменит метод GetFillName в классе TMyUniverClass новой версией метода.


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

Для того, чтоб метод стал виртуальным, необходимо указать словао virtual после метода, а для того, чтоб метод стал динамическим, не обходимо указати слово dynamic.

type

TMyClass = class

function GetFillName: String; Virtual; // Виртуальный метод

function Dinamo: String; Dynamic; // Динамический метод

end;


Абстрактными называются динамические или виртуальные методы, которые не совершают никаких действий. Такие методы нужны для создания иерархии методов.

type

TMyClass = class

function GetFillName: String; Virtual; abstract;

end;


В любом объекте есть две процедуры: Create и Destroy. Одна называется Конструктор, другая – деструктор. Так, как классы (объекты) – динамические структуры, то Конструктор создаёт объект, а Деструктор его разрушает.

type

TMyClass = class

Constructor Create;

Destructor Destroy;

function GetFillName: String; Virtual; abstract;

end;


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


Для разрушения объектов существует так же метод Free. Данный метод перед выполнением команды Destructor вначале проверяет был ли в самом деле создан объект. Поэтому, более корректно вызывать метод Free.

События


Событие – это свойство процедурного типа, и его значением является указатель на некоторый метод. Позже, при рассмотрении графической среды разработки Вы столкнётесь с этим понятием много раз. Каждый раз, когда Вы щелчком на событии в среде разработки создаёте новое событие, компилятор связывает созданное событие с полем для события в компоненте. [7]


© 2006 Рудюк С.А. http://nerusoft.com

 

 

 

 

 Предложения


 Акции и объявления

Для партнёров скидки
-10%


 На правах рекламы


 
:: О нас :: Координаты :: Прайс-лист :: Форум :: Статьи :: Наши клиенты ::
Яндекс цитирования
© Copyright 1997-2008 RS™