Применение объектов
В последующем изложении во многих примерах будут рассматриваться особенности выполнения различных алгоритмов не над фактическими данными, а над указателями, задающими расположение этих данных. Необходимость этого состоит в отделении особенностей физического и логического представления данных от обрабатываемых их алгоритмов. Разделяя данные и средства манипулирования ими, мы будем больше основное внимание уделять характеристикам алгоритмов, а не заниматься ненужной разработкой или оптимизацией методов для числовых, строковых и любых другим типов данных.
Поскольку фактически будет проводиться работа с указателями, имеет смысл использовать структуры данных, которые хранят элементы в форме указателей. Таким образом, совокупность обрабатываемых данных должна быть определенным образом организована посредством своих указателей.
Класс TList предоставляет возможность организовать работу со списком разнотипных объектов посредством указателей. Класс позволяет добавлять, удалять, перегруппировывать, сортировать и получать доступ к объектам, на которые указывают элементы списка.
Для доступа к элементу списка служит свойство класса:
List: PPointerList;
которое представляет структуру:
PPointerList = ^TPointerList;
TPointerList = array[0..MaxListSize-1] of Pointer;
Перед работой с объектом списка его необходимо создать путем вызова конструктора:
var aList: TList;
...
aList:=TList.Create;
...
Try
...
Finally
aList.Free;
end;
Свойство Items позволяет выполнить обращение к элементу массива через методы чтения- записи для проверки на выход за диапазон. Свойство List выполняет прямое обращение без проверки и по скорости доступа выше. Например, для сохранения в объекте aList указателя p под первым порядковым номером следует выполнить обращение:
aList.Items[0]:=p;
или поскольку свойство Items является свойством по умолчанию:
aList[0]:=p;
Свойство Count содержит общее число элементов списка. Не все элементы списка содержат фактические указатели, некоторые могут содержать адресный ноль nil. Увеличение значения свойства Count приведет к добавлению в конец списка nil-элементов, а уменьшение – удаление элементов с конца списка. Метод Pack служит для удаления всех nil-элементов из списка и коррекции значения Count.
Свойство Capacity предназначено для управления динамической памятью при добавлении элементов. Чтение свойства позволит определить количество объектов, которые список может хранить без включения механизма перераспределения памяти. Добавление нового элемента приводит к автоматическому увеличению значения емкости. Для повышения быстродействия перед добавлением большого числа «тяжеловесных» объектов желательно предварительно задать свойство Capacity:
aList.Clear;
aList.Capacity:=Count;
for i:=1 to Count do List.Add(...);
Метод Add добавляет новый элемент, заданным своим указателем, в конец списка и возвращает его порядковый номер (индекс).
function Add(Item: Pointer): Integer;
Метод Clear удаляет все элементы из списка и устанавливает счетчик Count в 0.
Для удаления элемента из списка, заданного своим порядковым номером, служит метод Delete. После выполнения метода все элементы, следовавшие за удаленным, будут смещены, а значение счетчика уменьшено на единицу. Метод не освобождает память, ассоциированную с удаленным элементом.
procedure Delete(Index: Integer);
Метод Remove удаляет первый найденный элемент, заданный указателем, и возвращает порядковый номер элемента, предшествовавший удаленному. После выполнения метода все элементы, следовавшие за удаленным, будут смещены, а значение счетчика уменьшено на единицу.
function Remove(Item: Pointer): Integer;
Метод Extract удаляет элемент списка по указателю.
function Extract(Item: Pointer): Pointer;
Метод Exchange меняет местами содержимое двух элементов, заданных порядковыми номерами.
procedure Exchange(Index1, Index2: Integer);
Методы First и Last возвращают первый и последний элементы списка:
function First: Pointer;
function Last: Pointer;
Метод IndexOf возвращает порядковый номер первого вхождения элемента в список. При отсутствии элемента функция возвращает -1.
function IndexOf(Item: Pointer): Integer;
Метод Insert помещает элемент в заданную позицию списка. Все элементы, начиная с заданного, смещаются вверх на один.
procedure Insert(Index: Integer; Item: Pointer);
Метод Move перемещает указатель с первой позиции на вторую.
procedure Move(CurIndex, NewIndex: Integer);
Метод Sort выполняет сортировку элементов списка в соответствии с функцией сравнения.
procedure Sort(Compare: TListSortCompare);
Прототип функции следующий:
TListSortCompare = function(Item1, Item2: Pointer): Integer;
Функция должна возвращать положительное целое, при Item1 < Item2, 0 при равенстве и отрицательное целое при Item1 > Item2.
При уничтожении объекта списка TList память, выделенная под элементы, не освобождается. В таких случаях говорят, что объект не владеет своими данными. В некотором роде это преимущество, поскольку можно быть уверенным в сохранности данных. Однако существует проблема, связанная с ручным освобождением элементов списка. Следующий код удаления некорректен:
for i:=0 to aList.Count-1 do
Begin
TObject(aList[i]).Free;
aList.Delete(i);
end;
Ошибка заключается в том, что при очередном удалении элемента уменьшается общее их количество, а верхняя граница переменной цикла остается прежней. Правильнее было бы организовать обратный цикл и начать удалять с последнего элемента:
for i:=aList.Count-1 downto 0 do
Begin
TObject(aList[i]).Free;
aList.Delete(i);
end;
Контрольные вопросы
1. Что представляет собой объектный тип?
2. В чем заключается идея сокрытия информации?
3. Для чего необходимы директивы видимости и свойства?
4. Опишите способы структурированной обработки ошибок.
5. Приведите примеры описания классов и использования объектов.
Дата добавления: 2021-12-14; просмотров: 288;