Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

3583

.pdf
Скачиваний:
1
Добавлен:
08.01.2021
Размер:
595.84 Кб
Скачать

сумма – float

10.ЦЕХ имя – char*

начальник – char* количество работающих – int

11.ПЕРСОНА имя – char*

возраст – int

пол – int(bool)

12.АВТОМОБИЛЬ марка – char* мощность – int стоимось – float

13.СТРАНА

имя – char*

форма

правления – char* площать – float

14.ЖИВОТНОЕ имя – char*

класс – char* средний вес – int

15.КОРАБЛЬ имя – char*

водоизмещение – int

тип – char*

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

1.Что такое конструктор? Для чего он используется? 2.Что такое деструктор? Какой формат его описания?

3.Как определяется указатель на компоненту-функцию?

4.Как определяется указатель на экземпляр класса?

Лабораторная работа №3. Структура класса компонента.

1.Цель лабораторной работы.

Целью лабораторной работы является освоение практических навыки создания иерархии классов и использования статических компонентов класса.

2.Теоретический материал для домашнего изучения.

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

Файл EditLetNum.h: #ifndef EditLetNumH fdefine EditLetNumH

// ---------------------------------------------------------------

finclude <SysUtils.hpp> linclude<Controls.hpp> linclude <Classes.hpp> #include <Forms.hpp> finclude <StdCtrls. hpp>

// ---------------------------------------------------------------

class PACKAGE TEditLetNum : public TEdit

{

private:

protected:

public:

__fastcall TEditLetNum(TComponent* Owner); __published:

}; // ---------------------------------------------------------------

#endif

Файл EditLetNum.cpp: tinclude <vcl.h> #pragma hdrstop finclude "EditLetNum.h"

#pragma package(smart_init)

// -------------------------------------------------------------

//(Функция ValidCtrCheck используется для проверки того,

//что компонент не содержит чистых виртуальных функций)

static inline void ValidCtrCheck{TEditLetNum *)

{

new TEditLetNum(NULL);

}

// ---------------------------------------------------------------

__fastcall TEditLetNum::TEditLetNum(TCompanent* Owner) : TEdit(Owner)

{

}

// ---------------------------------------------------------------

namespace Editletnum {

void __fastcall PACKAGE Register()

{

TComponentClass classes[1] = {__classid(TEditLetNum)};

RegisterComponents("Мои компоненты", classes, 0);

}

}

Собственно говоря, в этой заготовке пока только каркас класса будущего модуля. Файл EditLetNum.cpp содержит три процедуры:

ValidCtrCheck, конструктор TEditLetNum и Register. Процедура

ValidCtrCheck носит вспомогательный характер и вводится, чтобы проверять, не содержит ли компонент чистых виртуальных функций. Тело

конструктора TEditLetNum пока пустое. Позднее оно будет заполнено. А

процедуру Register, регистрирующую компонент на заданной странице библиотеки.

Код регистрации компонента начинается с оператора namespace.

Ключевое слово namespace устанавливает локальность имен данной процедуры регистрации. После этого ключевого слова следует имя файла,

содержащего компоненты. Имя пишется символами в нижнем регистре,

кроме первой заглавной буквы.

В процедуре регистрации Register первый оператор создает массив регистрируемых компонентов classes тнпа TComponentClass и заносит в него регистрируемый компонент. Если бы вы создали два компонента

(пусть имя второго из них TEdit2), регистрируемых на одной странице библиотеки, вы моглн бы занести их в массив оператором:

TComponentClass classes [2] = {__classid(TEditLetNum), __classid(TEdit2)};

Следующий оператор процедуры регистрации регистрирует функцией

RegisterComponents компоненты, занесенные в classes (второй параметр функции) на странице Мои компоненты (первый параметр). Последний параметр является последним индексом массива регистрируемых компонентов.

Теперь рассмотрим коротко описание класса в заголовочном файле

EditLetNum.h. В нем есть разделы private, protected, public и __published.

Они определяют четыре варианта доступа к переменным, процедурам и функциям:

private

Процедуры и функции, определенные таким

(закрытые)

образом, доступны только в пределах данного

 

модуля.

 

 

protected

Процедуры и функции, определенные таким

(защищенные)

образом, доступны в классах потомков.

 

 

public (открытые)

Эти процедуры и функции доступны везде.

 

 

__published

Процедуры и функции доступны везде и

(опубликованные)

имеют связь со средой разработки C++Builder,

 

обеспечивающую вывод на экран в

 

Инспекторе Объектов страниц информации о

 

свойствах и событиях.

 

 

Определение объекта (компонент — это объект) выступает как совокупности свойств, методов и обработчиков событий. Причем свойства

— это совокупность полей данных и методов их чтения и записи.

Вспомним также принцип скрытия информации. Исходя из этого,

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

Задание свойств

Поля данных всегда должны быть защищены от несанкционированного доступа. Поэтому их целесообразно определять в private — закрытом разделе класса. В редких случаях их можно помещать в protected —

защищенном разделе класса, чтобы возможные потомки данного класса имели к ним доступ. Традиционно идентификаторы полей совпадают с именами соответствующих свойств, но с добавлением в качестве префикса символа ―F‖. Таким образом, в нашем примере вы можете занести в раздел private объявления трех необходимых нам полей данных:

class PACKAGE TEditLetNum : public TEdit

{

private:

// Закрытые элементы-данные класса bool FEnableNum;

bool FEnableLet; bool FModified; } ;

Теперь надо объявить свойства — методы чтения и записи этих полей.

Свойство объявляется оператором вида:

__property <тип> <имя> = {read=<имя поля или метода чтения> write=<имя поля или метода записи> <директивы запоминания и значения по умолчанию>;

Если в разделах read или write записано имя поля, значит,

предполагается прямое чтение или запись данных.

Если в разделе read записано имя метода чтения, то чтение будет осуществляться только функцией с этим именем. Функция чтения — это функция без параметра, возвращающая значение того типа, который объявлен для свойства. Имя функции чтения принято начинать с префикса

Get, после которого следует имя свойства.

Если в разделе write записано имя метода записи, то запись будет осуществляться только процедурой с этим именем. Процедура записи — это процедура с одним параметром того типа, который объявлен для свойства. Имя процедуры записи принято начинать с префикса Set, после которого следует имя свойства.

Если раздел write отсутствует в объявлении свойства, значит это свойство только для чтения и пользователь не может задавать его значение.

Директивы запоминания определяют, как надо сохранять значения свойств при сохранении пользователем файла формы *.dfm. Чаще всего используется директива

default = <значение по умолчанию>

Она не задает начальные условия. Это дело конструктора. Директива просто говорит, что если пользователь в процессе проектирования не изменил значение свойства по умолчанию, то сохранять значение свойства не надо.

Итак, для нашего примера объявления свойств могут иметь вид: public:

__fastcall TEditLetNum(TComponent* Owner); // Свойство только времени выполнения

__property bool Modified = {read=FModified, default=false}; __published:

// Свойства компонента, включаемые в Инспектор Объектов

__property bool EnableLet = {read=FEnableLet, write=SetEnableLet, default=true};

__property bool EnableNum = {read=FEnableNum, write=SetEnableNum, default=true};

Объявление свойства Modified помещается в раздел public, поскольку это свойство должно быть доступно только во время выполнения.

Свойства EnableNum и EnableLet помещаются в раздел published, так как они должны отображаться в Инспекторе Объектов во время проектирования.

Свойства EnableNum и EnableLet имеют прямой доступ к полям для чтения. Но для записи они имеют методы SetEnableNum и SetEnableLet

соответственно. Это связано с тем, что при записи свойств надо проверять,

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

Свойство Modified вообще не имеет метода записи, поскольку оно предназначено только для чтения.

Указанные в объявлениях методы записи могут быть реализованы обычными функциями, объявления которых помещаются в private —

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

Файл EditLetNum.h:

class PACKAGE TEditLetNum : public TEdit

{

private:

// Закрытые элементы-данные класса

bool FEnableLet; bool FEnableNum; bool FModified; protected:

// Защищенные методы записи

void __fastcall SetEnableLet{bool AEnableLet); void __fastcall SetEnableNum(bool AEnableNum);

public:

// Объявление конструктора

__fastcall TEditLetNum(TComponent* Owner); // Свойство только времени выполнения

__property bool Modified = {read=FModified, default=false}; _ published:

// Свойства компонента, включаемые в Инспектор Объектов

__property bool EnableLet = {read=FEnableLet, write=SetEnableLet, default=true};

__property bool EnableNum = {read=FEnableNum, write=SetEnableNum, default=true};

} ;

Файл EditLetNum.cpp:

static inline void ValidCtrCheck(TEditLetNum *) {

new TEditLetNum(NULL);

}

//--------------------------------------------------------------------

__fastcall TEditLetNum::TEditLetNum(TComponent* Owner) : TEdit(Owner)

{

FEnableLet = true;

FEnableNum = true;

FModified = false;

}

//--------------------------------------------------------------------

namespace Editletnum {

void _ fastcall PACKAGE Register()

{

TComponentClass classes[l] = {__classid{TEditLetNum)); RegisterComponents{"MyComponents", classes, 0);

}

}

//--------------------------------------------------------------------

void __fastcall TEditLetNum::SetEnableNum(bool AEnableNum)

{

//Присваивание значения полю FEnableNum FEnableNum = AEnableNum;

//Если значения FEnableNum и FEnableLet = false,

//то полю FEnableLet присваивается true if(!AEnableNum)

if(!FEnableLet) FEnableLet = true;

}

//---------------------------------------------------------------------------------------

void __fastcall TEditLetNum:: SetEnableLet(bool AEnableLet)

{

//Присваивание значения полю FEnableLet FEnableLet = AEnableLet;

//Если значения FEnableNum и FEnableLet = false,

//то полю FEnableNum присваивается true if(!AEnableLet)

if(!FEnableNum) FEnableNum = true;

}

Процедуры, реализующие методы записи, присваивают полю переданное в них значение параметра и в случае, если передано значение false, проверяют значение другого поля. Если и другое поле имеет значение false, то оно исправляется на true.

Объявления процедур записи включены в раздел protected. Это означает, что они закрыты для внешнего пользователя, но доступны для возможных потомков вашего класса.

Конструктор объявлен в открытом разделе класса public и имеет имя

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

Теперь давайте сохраним подготовленные файлы, откомпилируем их

(кнопка Compile в Диспетчера Пакетов) и построим тестовое приложение для отладки установленного компонента. Хотя он еще не до конца создан,

кое-что уже можно увидеть.

Откройте новый проект и внесите в него с соответствующей страницы библиотеки ваш новый компонент. Откройте (командой File | Open) файл вашего компонента, чтобы можно было вносить в него какие-то изменения. Сохраните проект под каким-нибудь именем (например,

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]