Нехватка памяти возможна и в случае статических объектов с динамическими полями. Так, при размещении конструктором динамических полей в куче может возникнуть нехватка памяти. Но, поскольку объект статический, нельзя передать сигнальное значение nil в ссылку — ее попросту нет. Вместо этого предлагается использовать имя конструктора как логическую функцию. Если внутри конструктора была вызвана процедура Fail, то в имени конструктора вернется значение False. В остальных случаях будет возвращаться значение True. Подобным способом анализа можно пользоваться и для проверки работы унаследованных конструкторов.

На рис. 13.8 приводится пример объектов (динамических и с динамическими полями) и их инициализация с обработкой возможных ошибок.

| TYPE

| VectorType = Array [ 1..1000 ] of Real; { вектор }

| MatrixType = Array [1..20,1..20 ] of Real; { матрица }

| VectorTypePtr = ^VectorType; { ссылка на вектор }

| MatrixTypePtr = ^MatrixType; { ссылка на матрицу }

| Vector = OBJECT {статический объект с динамическим полем }

| V : VectorTypePtr;

| CONSTRUCTOR Init( FillVect : Real );

| DESTRUCTOR Done; VIRTUAL;

| PROCEDURE Work; VIRTUAL;

| END;

| ComplexPtr = ^Complex; { Динамический объект с }

| Complex = OBJECT(Vector) { динамическими полями данных }

| M : MatrixTypePtr,

| CONSTRUCTOR Init(FillVect, FillMat : Real);

| DESTRUCTOR Done;

| VIRTUAL;

| PROCEDURE Work; VIRTUAL;

| END;

| { Реализация методов объектов }

| CONSTRUCTOR Vector.Init( FillVect : Real );

| VAR i : Word; { параметр цикла заполнения }

| BEGIN

| New( V ); { попытка разместить V в куче }

| if V=nil then begin

{ при неудаче сделать откат }

| Vector.Done; { завершение работы объекта }

| Fail { объявить сбой конструктора }

| end; {if}

| for i:=1 to 1000 do

|{ поле V создано и заполняется }

| V^[i] := FillVect;

| END;

| DESTRUCTOR Vector.Done;

| BEGIN

| if V<>nil then Dispose( V )

|{ освобождение поля V }

| END;

| PROCEDURE Vector.Work; { метод обработки поля V }

| BEGIN

| { Какие-либо действия над вектором V^ }

| END;

- 291 -

| CONSTRUCTOR Convex.Init( FillVect, FillMat : Real );

| VAR i,j : Word; { параметры циклов заполнения}

| BEGIN

| if not Vector.Init(FillVect) {инициализация прародителя }

| then Fail; {при неудаче сделать откат }

| New( M ); { попытка разместить M в куче }

| if M=nil then begin

{ при неудаче сделать откат }

| Complex.Done; { завершение работы объекта }

| Fail { объявить сбой конструктора }

| end; {if}

| for i:=1 to 20 do

| {поле М создано и заполняется }

| for j:=1 to 20 do

| M^[i,j] := FillMat;

| END;

| DESTRUCTOR Complex.Done;

| BEGIN

| if M<>nil then Dispose( M );

|{ освобождение поля M }

| Vector.Done { освобождение поля V }

| END;

| PROCEDURE Complex.Work; { метод обработки поля М }

| BEGIN

| { Какие-либо действия над матрицей M^ }

| END;

| {$F+} { новая функция анализа распределения памяти}

| FUNCTION HeapFunc(Size: Word) : Integer;

| BEGIN

| HeapFunc := 1

| END;

| {$F-}

| VAR

| Vec : Vector; { экземпляр статического объекта}

| ComPtr : ComplexPtr; { ссылка на динамический объект }

| BEGIN

| HeapError := @HeapFunc; { подстановка функции анализа }

| if not Vec.Init( 1.0 ) { инициализация поля Vec.V }

| then Halt( 1 ); { реакция на неудачу операции }

| New(ComPtr, Init(2,3)); { размещение объекта ComPtr^ }

Перейти на страницу:

Поиск

Похожие книги