Освободить память, выделенную объекту конструктором.




Лабораторная работа № 39

Решение задач с использованием конструкторов и деструкторов

Цель работы: научиться решать задачи с использованием конструкторов и деструкторов на Object Pascal в инструментальной среде разработки Delphi. Овладение практическими навыками создания и уничтожения объекта с использованием методов Create и Destroy.

Ход работы:

Объекты сами являются структурными элементами, у каждого объекта есть свои собственные свойства и возможные действия (методы). Например, щелкать по окну бессмысленно, потому что у объекта «окно» не предусмотрено действия - реакции на щелчок мыши.

Для объекта можно указывать свойства и методы.

Свойство объекта – это программно предусмотренные параметры объекта.

Метод объекта – это действия, которые программно описаны для данного объекта.

Свойства объекта – это цвет, форма, положение, имя и т.д. Метод объекта – это реакция на событие (щелчок мышью, изменение формы объекта и т.д,). Набор свойств и событий для каждого объекта представлен в «Инспекторе объектов».

Свойства объектов задаются через поля, а методы, через соответствующие процедуры и функции.

Пример.
Объект "кнопка" имеет свойство "цвет". Значение цвета кнопка запоминает в одном из своих полей. При изменении значения свойства "цвет" вызывается метод, который перерисовывает кнопку.
Задание 1. Составьте и постоянно пополняйте таблицу свойств и методов объектов по образцу:

Таблица свойств и методов объектов:

Объект Свойства Методы
Кнопка (Button) Сар tion (заголовок) Show (показать)
  Top (расстояние от верхнего края)  
  ….  
Меню (Menu)    
Раскрывающийся список (Combo Box)    
Надпись (Label)    
Флажок (Checkbox)    
Переключатель (RadioButton, Option Button)    
Корешок вкладки (Tab)    
Текстовое поле (Edit box или просто Edit, Text box)    
и так далее    

Если в программе используется несколько кнопок, текстовых полей или меню, то мы говорим о классе объектов.

Класс объектов – это категория объектов, обладающих одинаковыми свойствами и поведением.

Так как класс – это совокупность объектов, то он также имеет поля, методы, свойства.

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

Объекты являются конкретными представителями своего класса, их принято называть экземплярами класса.

Объекты

Свойства Каждый объект обладает набором свойств. Значение свойств можно изменить в программном коде.   Объект. Свойство = Значение свойства Методы Для того чтобы объект выполнил какую-либо операцию, необходимо применить метод, которым он обладает. Методы имеют аргументы, которые позволяют задать параметры выполняемых действий.   Объект. Метод арг 1: = зн, арг 2: = знач. События Событие представляет собой действие, распознаваемое объектом. Событие может создаваться пользователем или быть результатом взаимодействия других программных объектов. В качестве реакции на событие вызывается определенная процедура.

Для описания нового класса в языке Object Pascal определен следующий синтаксис:

Type <имя объявляемого класса>= class(<имя родительского класса>
  Private
    <скрытые элементы класса>
  Protected
    <защищенные элементы класса >
  Public
    <общедоступные элементы класса >
  Publiched
    <опубликованные элементы класса >
End;

Cекция Private содержит внутренние элементы, обращение к которым возможно только в пределах модуля, содержащего объявление класса.

Секция Protected содержит защищенные элементы, которые доступны в пределах модуля, содержащего объявление класса, и внутри классов-потомков.

Cекция Public содержит общедоступные элементы, к которым можно обращаться из любой части программы.

Cекция Publiched содержит опубликованные элементы, которые по ограничению доступа аналогичны Public. Информация об элементах визуальных компонент, размещенных в этой секции, доступна через инспектор объектов.

Каждый класс может породить другой класс. Потомки класса могут менять область доступности всех элементов родительского класса, кроме элементов, объявленных в рrivate, так как они им недоступны. Все объекты Delphi являются динамическими, т.е. располагаются в динамической области памяти. Соответственно переменная типа класса по смыслу представляет указатель на объект. Поэтому вызовы конструктора и деструктора являются обязательными. Конструктор выполняет размещение объекта в памяти, а деструктор – освобождение памяти от объекта.

Например, разработка класса, поля которого используются для описания положения точки на экране монитора.

Проектируемый класс должен содержать поля для сохранения координат точки (x и y), возможными действиями являются инициализация объекта, получение координат, разрушение объекта.

Определим класс Position:

Поля Fx, Fy предназначены для хранения значений координат. Поля принято обозначать начиная с символа F. Это внутренние данные класса и поэтому описаны в разделе Private.

Constructor Create предназначен для создания объекта (экземпляра класса), а также для определения первоначального значения полей. Destructor Destroy предназначен для удаления объекта из памяти.

Методы GetX и GetY возвращают координаты положения объекта.

Доступ к полям объекта осуществляется с использованием составного имени: <имя объекта>.<Имя поля>

Задание 2. Объясните программный код, который приведен ниже.

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
   
    { Private declarations }
  public
    { Public declarations }
end;

Какой класс описан? Что является полями и методами?

Что может происходить при наступлении события «щелчок мыши по кнопке»?

 

Create — это так называемый конструктор объекта; он всегда присутствует в классе и служит для создания и инициализации экземпляров. При создании объекта в памяти выделяется место только для его полей. Методы, как и обычные процедуры и функции, помещаются в область кода программы; они умеют работать с любыми экземплярами своего класса и не дублируются в памяти.

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

Reader.NextLine;

Кроме того, как и при работе с записями, допустимо использование оператора with, например:

with Reader do NextLine;

Если объект становится ненужным, он должен быть удален вызовом специального метода Destroy, например:

Reader.Destroy; // Освобождение памяти, занимаемой объектом

Destroy — это так называемый деструктор объекта; он присутствует в классе наряду с конструктором и служит для удаления объекта из динамической памяти. После вызова деструктора переменная Reader становится несвязанной и не должна использоваться для доступа к полям и методам уже несуществующего объекта. Чтобы отличать в программе связанные объектные переменные от несвязанных, последние следует инициализировать значением nil. Например, в следующем фрагменте обращение к деструктору Destroy выполняется только в том случае, если объект реально существует:

Reader:= nil; ... if Reader <> nil then Reader.Destroy;

Вызов деструктора для несуществующих объектов недопустим и при выполнении программы приведет к ошибке. Чтобы избавить программистов от лишних ошибок, в объекты ввели предопределенный метод Free, который следует вызывать вместо деструктора. Метод Free сам вызывает деструктор Destroy, но только в том случае, если значение объектной переменной не равно nil. Поэтому последнюю строчку в приведенном выше примере можно переписать следующим образом.

Reader.Free;

После уничтожения объекта переменная Reader сохраняет свое значение, продолжая ссылаться на место в памяти, где объекта уже нет. Если эту переменную предполагается еще использовать, то желательно присвоить ей значение nil, чтобы программа могла проверить, существует объект или нет. Таким образом, наиболее правильная последовательность действий при уничтожении объекта должна быть следующая:

Reader.Free; Reader:= nil;

С помощью стандартной процедуры FreeAndNil это можно сделать проще и элегантнее:

 

Задание 3. Проект «Фигуры»

Научиться создавать и уничтожать экземпляры класса TShape.

При нажатии на кнопку " Соз­дать объект " наша программа должна будет создать круг со случайны­ми параметрами (размер, цвет) и поместить его в произ­вольном месте панели. При нажатии на кнопку " Удалить объект " программа должна выполнить два действия:

1. уда­лить изображение объекта с экрана

освободить память, выделенную объекту конструктором.

Ход работы:

Начните новый проект в Delphi и сохраните его в отдельной папке под названием “ Figures ”. Разместите на форме компоненты, показанные на рисунке.

Пусть переменная AObj имеет тип TShape, тогда минимальный набор операторов для ее создания следующий:

AObj:=TShape.Create(Panel1); // Создаем объект AObj типа TShape на панели Panel1

AObj.Parent:=Panel1; // Указываем ссылку на объект-владелец (место «рождения»)

После этого можно задать свойства, определяющие же­лаемый вид объекта. Если этого не сделать, то их значения останутся теми, которые установлены в конструкторе (значения «по умолчанию).

Однако при повтор­ном нажатии на кнопку " Создать объект " вновь созданный объект запишется в ту же перемен­ную AObj. И хотя на экране мы будем видеть два круга, на самом деле доступ к первому из них будет потерян! Поэтому нам необходимо хранить создан­ные объекты в массиве или списке. Если мы не знаем зара­нее, сколько объектов создадим, то лучше использовать спи­сок TList. Фактически это массив, размер которого увели­чивается в процессе заполнения, что избавляет программи­ста от лишних хлопот. В его свойстве Items хранятся указате­ли типа Pointer, поэтому элементами списка могут быть объекты любого типа.

Вставьте в модуль объявление переменной List типа TList:

var

Form1: TForm1;

List: TList;

implementation

{$R *.DFM}

По­скольку список является классом Delphi, то его (список) тоже необходимо создать по общим правилам.

Щелкните по пустому месту формы, перейдите на вкладку Events инспектора, щелкните дважды по полю ввода события OnCreate и добавьте в созданный Delphi шаблон строку, отмеченную ниже жирным шрифтом:

procedure TForm1.FormCreate(Sender: TObject);

begin

List:=TList.Create;

end;

Количество элементов в списке фиксируется в свойстве Count. Добавление нового объекта в список вне зависимости от его типа производится методом Add (при этом Count увеличивается на единицу), удаление – методом Delete (при этом Count уменьшается на единицу). Однако нужно помнить, что элементами списка являются указатели, следовательно, удаление указателя из списка не удаляет сам объект из памяти. Поэтому при закрытии формы, прежде чем удалить список, следует освободить память, занятую созданными объектами.

Перейдем к созданию нашей программы.

Щелкните дважды по кнопке Button1 («Создать объект») и добавьте в созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:

procedure TForm1.Button1Click(Sender: TObject);

var AObj: TShape; delta: word;

begin

// создаем новую фигуру

AObj:=TShape.Create(Panel1);

AObj.Parent:=Panel1;

// форма фигуры - круг

AObj.Shape:=stCircle;

// диаметр круга - случайное число от 10 до 60

delta:=10+random(50);

AObj.Width:=delta;

AObj.Height:=delta;

// "разыгрываем" место круга внутри панели

AObj.Left:=random(Panel1.Width-AObj.Width);

AObj.Top:=random(Panel1.Height-AObj.Height);

// задаем цвет круга

AObj.Brush.Color:=RGB(random(256),random(256),random(256));

// добавляем созданную фигуру в список

List.Add(AObj);

end;

Щелкните дважды по кнопке Button2 («Удалить объект») и добавьте в созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:

procedure TForm1.Button2Click(Sender: TObject);

var Temp: TShape;

begin

With List do

if Count>0 then begin

Temp:=Items[Count-1]; // В Temp – ссылка на последний созданный объект

Temp.Free;

Delete(Count-1);

end;

end;

Щелкните дважды по кнопке Button3 («Удалить все») и добавьте в созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:

procedure TForm1.Button3Click(Sender: TObject);

var Temp: TShape;

begin

With List do

while Count>0 do begin

Temp:=Items[Count-1];

Temp.Free;

Delete(Count-1);

end;

end;

Щелкните по пустому месту формы, перейдите на вкладку Events инспектора, щелкните дважды по полю ввода события OnClose и добавьте в созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

Button3.Click; // запускаем процедуру удаления объектов

List.Free; //удаляем список указателей

end;

И, наконец, поскольку фигуры на панели будут возникать случайным образом, необходимо будет вызвать один раз в программе процедуру Randomize, которая подготавливает к работе датчик случайных чисел. Можно сделать это в событии OnCreate формы, но мы для разнообразия используем секцию initialization нашего модуля. Для этого поместим в самый конец модуля следующие строки:

…………………..

Initialization

randomize;

end.

На рисунке приведен примерный вид окна программы после запуска.

Самостоятельная работа:

Задание 1

Разработать класс для построения точки на экране монитора. Точка имеет координаты X, Y и цвет Color.

Задание 2

Попробуйте переделать проект «Фигуры» так, чтобы кроме кругов на панели появлялись фигуры и другой формы. Программу разместите в отчете!!!

Содержание отчета:

1. Наименование, тема, цель работы.

2. Содержание заданий самостоятельной работы.

3. Таблица идентификаторов по форме:

Название объекта Вкладка окна Object Inspector Имя свойства / имя события Действие объекта

4. Результат выполнения и выводы.

Контрольные вопросы:

1. Что такое класс? Объект?

2. Поля, методы и свойства объектов.

3. Возможные секции в описании класса?

4. Алгоритм создания и уничтожения объекта.

5. Опишите методы Create и Destroy.

6. Какие объекты вы использовали в программе? Дайте описание полей, свойств и методов.

Задание 1 Использование конструктора для создания объекта «Кнопка»: на форме вашей программы находится кнопка "Дополнительно...", при нажатии на которую ваша форма должна увеличиться в размерах и на ней должны появиться дополнительные элементы управления.

Ход решения:

Установите на форму кнопку Button1 (Caption = "Дополнительно...")

Щелкните на кнопке Button1 и внесите в появившуюся заготовку следующий код:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

procedure MyAction(Sender:TObject);

public

{ Public declarations }

end;

var

Form1: TForm1;

btn: TButton; //Переменная для кнопки

edt: TEdit; //Переменная для Edit'а

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

begin

Form1.Height:=Form1.Height+40; //Увеличиваем размер формы

Button1.Enabled:=false; //Отключаем кнопку

btn:=TButton.Create(Form1); //Создаем новую кнопку

btn.Parent:=Form1; //Устанавливаем расположение новой кнопки

btn.Top:=Form1.Height div 2+20;

btn.Left:=10;

btn.Width:=100;

btn.Height:=25;

btn.Caption:='Новая кнопка';

btn.OnClick:=MyAction;

edt:=TEdit.Create(Form1); //Создаем новый Edit

edt.Parent:=Form1; //Устанавливаем расположение нового Edit'а

edt.Top:=Form1.Height div 2+20;

edt.Left:=120;

edt.Width:=100;

edt.Height:=25;

end;

procedure TForm1.MyAction(Sender: TObject);

begin

edt.Text:='Проверка';

end;

Запустите программу и нажмите на кнопку. Форма увеличит размеры и на ней появятся два новых компонента - кнопка и Edit. При нажатии на кнопку «Новая кнопка» в Edit будет выведен текст «Проверка».

Покажите результат работы преподавателю.

Задание 2 Массивы компонентов:

Динамическое создание компонентов можно использовать и для создания массивов компонентов.

Например, нам надо расположить на форме 3 кнопки. Если они будут выполнять в программе схожие функции, то лучше их оформить в виде массива. Для этого сначала этот массив объявляем:

...var Form1: TForm1; btn: Array[1..3] Of TButton;...

После этого добавьте в окно кода следующий обработчик для события OnCreate:

procedure TForm1.FormCreate(Sender: TObject); var i:Integer; begin for i:=1 To 3 do begin btn[i]:=TButton.Create(Form1); //Создаем кнопку btn[i].Parent:=Form1; //Задаем родительское окно btn[i].Top:=10; btn[i].Left:=10+60*(i-1); btn[i].Width:=50; btn[i].Height:=50; btn[i].Caption:=IntToStr(i) //Задаем заголовок для кнопки end end;

Теперь можете запускать программу. Будет создан массив из трех кнопок:

Покажите результат работы преподавателю.

 

Значение одной объектной переменной можно присвоить другой. При этом объект не копируется в памяти, а вторая переменная просто связывается с тем же объектом, что и первая:

Объекты могут выступать в программе не только в качестве переменных, но также элементов массивов, полей записей, параметров процедур и функций. Кроме того, они могут служить полями других объектов. Во всех этих случаях программист фактически оперирует указателями на экземпляры объектов в динамической памяти. Следовательно, объекты изначально приспособлены для создания сложных динамических структур данных, таких как списки и деревья. Указатели на объекты для этого не нужны.

Задание 3 Игра «Полоски»: создание модели известной игры со спичками. Правила игры заключаются в следующем: на ровную поверхность насыпается горка спи­чек, требуется снимать их по одной так, чтобы не сдвинуть остальные. В компьютерной модели " спичками " будут по­лоски — объекты TShape, которые довольно быстро появ­ляются в окне приложения, накладываясь друг на друга. Убрать можно только ту полоску, которая не перекрывает­ся никакой другой, — достаточно щелкнуть по ней мыш­кой. Игра считается оконченной, когда игроку удастся уб­рать все полоски.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-06-03 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: