Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП / ООП_Лекции.doc
Скачиваний:
50
Добавлен:
08.06.2015
Размер:
1.03 Mб
Скачать

Перегрузка функций

Вы можете определить в одной и той же области видимости несколько процедур или функций с одинаковыми именами, но различающихся по числу или типу параметров. Если после соответствующих объявлений поставить ключевое слово overload, то при вызове процедуры или функции с этим именем компилятор проанализирует передаваемые параметры, их число и тип и вызовет тот метод, который подходит данным параметрам. Например, вы можете определить следующие функ­ции:

function Divide(X, Y: Real): Real; overload;

begin

Result := X/Y;

end;

function Divide(X, Y: Integer): Integer; overload;

begin

Result := X div Y;

end;

Обе функции объявлены как перегруженные с именем Divide, но первая из них получает действительные аргументы, а вто­рая — целые. Значит, если будет записан вызов Divide(5,3), бу­дет вызываться первая функция, а при вызове Divide(5.0,3.0) — вторая.

Динамическое распределение памяти

Динамическое распределение памяти широко используется для экономии вычислительных ресурсов. Те переменные или объекты, которые становятся ненужными, уничтожаются, а освобожденное место используется для новых переменных или объектов. Это особенно эффективно в задачах, в которых число необходимых объектов зависит от обрабатываемых данных или от действий пользователя, т.е. заранее не известно. В этих ситуа­циях остается только два выхода: заранее с запасом отвести мес­то под множество объектов или использовать динамическое рас­пределение памяти, создавая новые объекты по мере надобности. Первый путь, конечно, неудовлетворительный, поскольку связан с излишними затратами памяти и в то же время накладывает на размерность задачи необоснованные ограничения.

Для динамического распределения выделяется специальная область памяти — heap (куча). Динамическое распределение па­мяти в этой области может производиться двумя различными способами: с помощью процедур New и Dispose и процедурами GetMem и FreeMem.

При первом способе выделение памяти производится процеду­рой

Procedure New(<имя указателя>);

где <имя указателя> — имя переменной, являющейся типизиро­ванным указателем. Этой переменной при успешном завершении процедуры передается адрес начала выде­ленной области памяти. Размер выделяемой области определяет­ся размером памяти, необходимым для размещения того типа данных, который указан при объявлении указателя.

Рассмотрим примеры динамического выделения памяти. Опе­раторы

var P: ^геаl;

New(P);

P^:=5.5;

объявляют переменную Р, являющуюся указателем на действи­тельное значение. Процедура New выделяет память для этого значения. А следующий оператор заносит в эту область чис­ло 5.5.

Приведенный ниже пример показывает выделение памяти под запись:

type

rec = record

fio:string[40] ;

year:integer;

end;

var Pr: ^rec;

New(Pr);

with Рr^ do begin

fio:='Иванов Иван Иванович';

year:= 1962;

end;

Освобождение памяти, динамически выделенной процедурой New, осуществляется процедурой Dispose:

procedure Dispose(<имя указателя>);

В эту процедуру должен быть передан тот указатель, в кото­ром хранится адрес области памяти, выделенной ранее процеду­рой New. Для приведенных выше примеров соответствующие процедуры Dispose могут быть записаны следующим образом:

Dispose(Р);

Dispose (Pr);

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

Второй способ динамического выделения памяти связан с при­менением процедур GetMem для выделения памяти и FreeMem для ее освобождения. Они имеют следующий синтаксис:

procedure GetMem(<имя указателя>,<объем памяти в байтах>) ;

procedure FreeMem(<имя указателя>,<объем памяти в байтах>);

В отличие от процедур New и Dispose здесь задается не только указатель, в котором устанавливается процедурой GetMem и чи­тается процедурой FreeMem адрес выделенной области памяти, но и указывается объем памяти в байтах. Благодаря этому в про­цедурах могут использоваться не только типизированные, но и нетипизированные указатели (см. раздел 2.13). Если же исполь­зуется типизированный указатель, то объем необходимой памяти лучше всего определять функцией SizeOf, так как размеры памяти, отводимой под тот или иной тип данных, могут изменяться в различных версиях компилятора. Таким образом, в приведен­ных выше примерах вызовы процедуры New могут быть замене­ны следующим образом:

GetMem(P, SizeOf(real);

FreeMemfP, SizeOf (real);

GetMem(Pr, SizeOf(rec);

FreeMem(Pr, SizeOf(rec);

Надо иметь в виду, что два рассмотренных метода нельзя сме­шивать. Например, нельзя освободить методом FreeMem память, выделенную ранее методом New, и нельзя освободить методом Dispose память, выделенную методом GetMem.

Вместо функции GetMem может использоваться функция АllocMem:

AllocMem(Size: Cardinal): Pointer

Она динамически выделяет область памяти размером Size байтов и возвращает указатель на выделенную область. Эта об­ласть в дальнейшем, как и в случае функции GetMem, может быть освобождена процедурой FreeMem.

При выделении памяти возможна генерация исключения, связанного с отсутствием достаточных резервов памяти. Для об­работки случаев нехватки памяти надо использовать перехват и обработку исключения EOutOfMemory.

Соседние файлы в папке ООП