- •Литература
- •Содержание
- •1. Основные понятия ооп
- •2. Программирование для Windows
- •3. Визуальное программирование и среда Delphi
- •Создание приложений в средеDelphi
- •Компоненты общего назначения tMainMenu- главное меню формы (программы)
- •TPopupMenu- вспомогательное (локальное) меню
- •TLabel- метка для отображения текста
- •TEdit-ввод и отображение строки
- •TMemo- ввод и отображение текста
- •TButton- кнопка
- •TBitBtn- кнопка с изображением
- •TSpeedButton- кнопка для инструментальных панелей
- •TCheckBox- независимый переключатель
- •TRadioButton- зависимые переключатели
- •TRadioGroup- группа зависимых переключателей
- •TListBox- список выбора
- •TComboBox- раскрывающийся список выбора
- •TPanel- панель
- •TTabControl- набор закладок
- •TPageControl- набор страниц с закладками
- •4. Особенности языка ооп Object Pascal
- •Процедуры и функции Выход из процедур и фукнций и возврат результата
- •Передача параметров
- •Параметры со значениями по умолчанию
- •Перегрузка функций
- •Динамическое распределение памяти
- •Указатели
- •Операции с указателями
- •Операция @
- •Самоадресуемые записи
- •Динамические массивы Одномерные динамические массивы
- •Многомерные динамические массивы
- •Исключения и их обработка
- •Защита кода зачистки в блокахtry...Finally
- •Защита кода зачистки на уровне модуля — разделfinalization
- •Обработка исключений в блокахtry...Except
- •Последовательность обработки исключений
- •5. Классы и объекты
- •Классы и объекты
- •Инкапсуляция
- •Наследование
- •Полиморфизм
- •Составляющие класса Поля
- •Одноименные методы
- •Свойства
- •События
- •Объявление класса
- •Операции с классами
- •Ссылки на классы
- •TObjectи информация о классах
- •Регистрация и обнаружение классов
- •6. Создание объектов во время выполнения, поиск компонентов
- •Клонирование объектов
- •Поиск компонента
- •Двукратное освобождение объекта
- •7. Построение собственных компонентов
- •Как и для чего следует строить компоненты
- •Общие руководящие принципы
- •Ключевые идеи
- •Компиляция компонентов
- •Отладка компонентов
- •Примечание
- •Примечание
- •Примечание
- •8. Работа с потоками
- •Классы потоковDelphi
- •Файловые потоки
- •Примечание
- •Методы потоков в действии: программаMemoStr
- •Потоки памяти
- •Пример программыMemoryS
- •Примечание
- •Написание заказного класса потока
- •9. Работа с com-объектами, использование серверов ole-автоматизации
Перегрузка функций
Вы можете определить в одной и той же области видимости несколько процедур или функций с одинаковыми именами, но различающихся по числу или типу параметров. Если после соответствующих объявлений поставить ключевое слово 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.