При инициализации массива в динамической памяти выделяется участок, в котором последовательно будут размещены его элементы. Указатель Orig на начало этого участка определен в секции Protected, поэтому он доступен потомкам класса TMas. Свойство Property Elem и методы OutElem и InpElem – для записи и чтения значений элементов определены в секции Public, а значит доступны в других модулях и программах.
При работе конструктора значения полей jMax и jMin в классе TMas передаются как параметры, определяющие количество элементов массива. Метод ElemP позволяет интерпретировать байты памяти, отведенные под элемент с номером j, как значение вещественного типа. Он записывается в секции Protected, поэтому он доступен потомкам класса TMas.
При описании метода ElemP исользуются:
- функция Sizeof(x) – дает размер аргумента x в байтах;
- функция Ptr(x:integer) – стандартная функция типа указатель, которая преобразует адрес памяти (адрес= сегмент + смещение) в указатель.
function TMas.ElemP;
begin
ElemP:=Ptr(LongInt(Orig)+(j-jMin)*Sizeof(Real));
end;
- вычисляется как функция Ptr от базового адреса (указатель Orig на начало области динамической памяти + смещение на j – jMin, умноженное на размер каждого элемента в байтах).
Рассмотрим описание конструктора и деструктора в модуле Massiv:
описание конструктора:
Процедуры GetMem и FreeMem выделяют и освобождают в динамической памяти область размера (jMax – jMin + 1)* Sizeof(Real) и присваивают адрес этой области указателю Orig. Метод Clearance очищает массив.
В классе TMas описываются методы Add, Sub, Mul, которые выполняются как двухместные операции. Здесь действуют соглашение: при выполнении двухместной операции первым операндом является сам объект, вторым операндом – тот, который является формальным параметром метода. Результат сохраняется в полях первого операнда.
Если в классе TMas не описывать свойство Elem[j:integer], то в модуле Unit Uses_Massiv, при использовании объектов класса TMas необходимо обращаться не к Elem[i], а к ElemP[i]^, а также к операциям InpElem и OutElem. Как пример ниже фрагмент процедуры вычисления z1:
Полное описание модуля Massiv, в котором описан класс TMas с операциями над координатами точек, необходимыми для решения задач аналитической геометрии, описано ниже:
unit Massiv;
interface
type Real=Single;
RealP=^Real;
type TMas=class
protected
Orig:Pointer;
{поле Orig используется как указатель адреса динамической
области}
jMin,jMax:Integer;
function ElemP(j:integer):RealP;
{метод определения адреса j-го элемента массива}
Public
function OutElem(j:integer):Real;
procedure InpElem(j:integer;r:Real);
{методы для чтения и записи j-го элемента массива}
constructor Create(jMin_,jMax_:integer);
destructor Destroy; override;
{деструктор перекрыт для динамического замещения в классе
потомке}
property Elem[j:integer]:Real read OutElem write InpElem;
default;
procedure Clearance; {метод для создания нулевого массива}
procedure Add(x:TMas); {метод сложения элементов массива}
procedure Sub(x:TMas); {метод вычитания элементов массива}
procedure Mul(x:TMas); {метод умножения элементов массива}
procedure Mulx(x:real); {метод умножения элемента на число }
procedure Divx(x:real); {метод деления элемента на число }
function Sum():Real; {метод сложения элементов массива}
function PMn(x:TMas;y:TMas):Real; {метод вычисления площади
ориентированного многоугольника}
end;
Методы класса описываются с использованием метода ElemP в разделе implementation:
implementation
uses Uses_Massiv;
function TMas.OutElem(j:integer):Real;
begin
Result:=ElemP(j)^;
end;
procedure TMas.InpElem(j:Integer;r:real);
begin
ElemP(j)^:=r;
end;
function TMas.ElemP;
begin
ElemP:=Ptr(LongInt(Orig)+(j-jMin)*SizeOf(Real));
end;
constructor TMas.Create;
begin
inherited Create;
jMin:=jMin_;
jMax:=jMax_;
GetMem(Orig,(jMax-jMin+1)*SizeOf(Real));
Clearance;
end;
destructor TMas.Destroy;
begin
FreeMem(Orig,(jMax-jMin+1)*Sizeof(Real));
inherited Destroy;
end;
procedure TMas.Clearance;
var j:integer;
begin
for j:=jMin to jMax do
ElemP(j)^:=0.0;
end;
procedure Tmas.Add;
var j:integer;
begin
for j:=jMin to jMax do
ElemP(j)^:=ElemP(j)^+x.ElemP(j)^;
end;
procedure Tmas.Sub;
var j:integer;
begin
for j:=jMin to jMax do
ElemP(j)^:=ElemP(j)^-x.ElemP(j)^;
end;
procedure Tmas.Mul(x:TMas);
var j:integer;
begin
for j:=jMin to jMax do
ElemP(j)^:=ElemP(j)^*x.ElemP(j)^;
end;
procedure Tmas.Mulx(x:real);
var j:integer;
begin
for j:=jMin to jMax do
ElemP(j)^:=ElemP(j)^*x;
end;
procedure Tmas.Divx(x:real);
var j:integer;
begin
for j:=jMin to jMax do
ElemP(j)^:=ElemP(j)^/x;
end;
function Tmas.Sum():real;
var j:integer; S:Real;
begin
S:=0;
for j:=jMin to jMax do
S:=S+ElemP(j)^;
Sum:=S;
end;
function TMas.PMn(x:TMas;y:TMas):Real;
var s:Real; j:Integer;
begin
s:=0;
for j:=jMin to jMax-1 do
begin
ElemP(j)^:=(x.ElemP(j)^-x.ElemP(j+1)^)*(y.ElemP(j)^+
y.ElemP(j+1)^);
s:=s+ElemP(j)^;
end;
ElemP(jMax)^:=(x.ElemP(jMax)^x.ElemP(jMin)^)*(y.ElemP(jMax)^
+y.ElemP
(Min)^);
PMn:=(s+ElemP(jMax)^)/2;
end;
end.