Академический Документы
Профессиональный Документы
Культура Документы
Технологии программирования
МОДУЛЬ № 1
Часть 2
Объектно-ориентированное программирование
Методические указания
к лабораторным и практическим занятиям
Одесса 2011
2
УДК 004.43 План УМИ 2011 г.
ОДОБРЕНО
на заседании кафедры
информационных технологий
и рекомендовано к печати
Протокол № 7
от 1 февраля 2011 г.
УТВЕРДЖЕНО
методическим советом
академии связи
Протокол № 8
от 11.02.2011
3
ПРЕДИСЛОВИЕ
Технология программирования играла разную роль на разных этапах раз-
вития программирования. По мере повышения мощности компьютеров и разви-
тия средств и методологии программирования росла и сложность решаемых на
компьютерах задач, что привело к повышенному вниманию к технологии про-
граммирования. Резкое удешевление стоимости компьютеров и, в особенности,
стоимости хранения информации на компьютерных носителях привело к широ-
кому внедрению компьютеров практически во все сферы человеческой дея-
тельности, что существенно изменило направленность технологии программи-
рования. Человеческий фактор стал играть в ней решающую роль. Сформиро-
валось достаточно глубокое понятие качества программного средства, причем
предпочтение стало отдаваться не столько его эффективности, сколько удобст-
ву работы с ним для пользователей (не говоря уже о его надежности). Широкое
использование компьютерных сетей привело к интенсивному развитию распре-
деленных вычислений, дистанционного доступа к информации и электронного
способа обмена сообщениями между людьми. Компьютерная техника из сред-
ства решения отдельных задач все более превращается в средство информаци-
онного моделирования реального и мыслимого мира, способное просто отве-
чать людям на интересующие их вопросы. Начинается этап глубокой и полной
информатизации (компьютеризации) человеческого общества. Все это ставит
перед технологией программирования новые и достаточно трудные проблемы.
Темы модуля
1. Операции с динамическими структурами данных. Проблемы и на-
правления развития технологий программирования. Динамические структуры
данных: стеки, очереди, списки, деревья. Программирование операций с дина-
мическими структурами данных.
2. Объектно-ориентированный подход в программировании. Модуль-
ное и объектно-ориентированное программирование. Понятие класса и объекта.
Поля и методы классов. Спецификаторы доступа к методам класса.
3. Построение классов и их потомков. Инкапсуляция. Наследования
классов. Конструкторы и способы их назначения. Деструкторы.
4. Полиморфизм. Перекрытие методов. Статические, виртуальные и дина-
мические методы. Абстрактные классы.
5. Классы и объекты библиотеки визуальных компонент. Иерархия
классов компонент системы программирования Borland С++. Использование
компонент-полей для визуализации объекта. Объекты-потомки классов
TComponent и TControl. Разработка собственных компонентов.
1 ЭЛЕМЕНТЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО
ПРОГРАММИРОВАНИЯ
Обратите еще раз внимание на то, что в этом примере все элементы класса
являются общедоступными, что предоставило возможность обращаться ко всем
элементам класса непосредственно через объекты bacalavr и magistr (на-
пример: bacalavr.name, magistr.show_student(), magistr.year()).
При создании класса можно иметь элементы, значения которых использу-
ются только в классе, но обращаться к которым в самой программе нет необхо-
димости. Такие элементы являются закрытыми (private), их следует скрывать
от главной (вызывающей) программы. По умолчанию в C++ считается, что все
элементы класса являются закрытыми. Обычно надо защищать элементы класса
от прямого доступа к ним, объявляя для них доступ private. Только при таком
доступе можно гарантировать пользователю программного продукта, что эле-
ментам класса будут присвоены допустимые значения.
Например, в приведенном выше примере программы, объекты bacalavr и
magistr используют поле birthday, которое может принимать значения толь-
ко в диапазоне от 1946 до 1996 (год рождения студента). Если элемент birth-
day есть общедоступный (как в примере), то программа может напрямую об-
ращаться к этому элементу, изменяя его значение без ограничений:
bacalavr. birthday = 1300;
magistr. birthday = 2150;
15
Если объявить поле birthday закрытым, то для присваивания ему значе-
ний нужно создать и использовать дополнительный метод класса. Например,
функция assign_birthday() может проверять, является ли значение поля до-
пустимым:
class student
{ private: // закрытое поле класса
int birthday;
public: // общедоступные поля и методы класса
AnsiString name;
........
int assign_birthday (int y); //функция проверки допустимости значений
........ };
// реализация функции проверки допустимости значений
int student::assign_birthday(int y)
{if ((y > = 1946) && (y <= 1996))
{ birthday = y; return (0);} // Успешное присваивание значения года
else return (-1); // Недопустимое значение
}
Методы класса, которые управляют доступом к элементам данных, − это
интерфейсные функции. При создании классов желательно использовать эти
интерфейсные функции для защиты данных.
Вышерассмотренные примеры демонстрируют способы использования ме-
тодов класса для инициализации полей (присваивания значений) объекта клас-
са. Удобной является инициализация поля объекта в момент его создания, а не
явный вызов в программе соответствующего метода (set_a(int num), assign_
birthday (int y)). Такую инициализацию данных можно реализовать с помо-
щью специального метода класса, который называется конструктором.
Текст программы:
//--------------------------------------------
class Interval
{private:
int hour,minute;
22
public:
Interval():hour(0), minute(0){} / / Конструктор по умолчанию
Interval(int h, int m); / / Конструктор с параметром
void setinterv(int h,int m){ minute=m%60; hour=h+m/60;}
int gethour(){return hour;}
int getminute(){return minute;}
Interval add_interv(Interval);
};/ / Реализация методов
Interval::Interval(int h,int m): hour(h), minute(m)
{hour+=minute/60;minute%=60;}
Interval Interval:: add_interv(Interval d2)
{Interval temp;
temp.minute = minute+d2.minute;
temp.hour = hour+d2.hour;
if(temp.minute>59){temp.minute-=60; temp.hour++;}
return temp;
}
// Обработчик на кнопку «Сумма t1+t2»
void __fastcall TForm1::Button1Click(TObject *Sender)
{ / / Создание объектов t1 и t2 с данными из Edit
Interval t1(StrToInt(Edit1->Text),StrToInt(Edit2->Text));
Interval t2(StrToInt(Edit3->Text),StrToInt(Edit4->Text));
Interval t; / / Объект класса по умолчанию
t=t1.add_interv(t2); / / Вычисление
Edit5->Text=IntToStr(t.gethour()); / / Вывод «часов»
Edit6->Text=IntToStr(t.getminute());/ / Вывод «минут»
}
В классе Interval имеются следующие методы: конструктор по умол-
чанию и конструктор с двумя параметрами; метод setinterv(), позволяющий
на любом этапе программы изменять поля класса; методы gethour()и
getminute(), возвращающие значения полей hour и minute соответственно;
метод add_interv(), позволяющий складывать два промежутка времени.
В обработчике события OnClick кнопки с названием “Сумма t1+t2” с по-
мощью конструктора с двумя параметрами определяются два объекта t1 и t2,
инициализирующие свои поля значениями, прочитанными из четырех тексто-
вых полей, которые заполнит пользователь перед нажатием кнопки. Затем с
23
помощью конструктора по умолчанию определяется объект t, которому в сле-
дующем операторе присваивается значение, возвращаемое методом
add_interv(), который вызван объектом t1 с аргументом t2. В результате
значение объекта t представляет собой сумму двух интервалов времени t1 и
t2. С помощью методов gethour() и getminute()получим значения полей
объекта t и выведем их в предназначенные для них текстовые поля.
Форма проекта с результатами вычислений:
Текст программы:
//Описание класса
class pram
{protected:
int x1,y1,x2,y2; //координаты прямоугольника − закрытые параметры
public:
pram(int ix1,int iy1,int ix2,int iy2); //конструктор
void figura();//функция изображения прямоугольника
float diag();//функция вычисления длины диагонали
27
void figurum(TColor); //функция избражения прямоугольника,
// закрашенного заданным цветом
void textcol(AnsiString s); //функция изображения заданного текста
};
// Реализация конструктора
pram:: pram(int ix1,int iy1,int ix2,int iy2)
{x1=ix1;y1=iy1;
x2=ix2;y2=iy2;
}
//Реализация функции изображения прямоугольника по размерам полей класса
void pram::figura()
{ Form1->Image1->Canvas->Brush->Color = clBlue;
Form1->Image1->Canvas->Rectangle(x1,y1,x2,y2);
}
// ----------------Кнопка «ПОКАЗАТЬ»-----------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Clear();// очистка Memo1 для результатов длины прямоугольника
Текст программы
// описание динамической структуры «очередь»
struct listec
{String Fio; // фамилия студента
int num; // балл по дисциплине информатика
listec *next; // указатель на следующий элемент
};
// описание класса
class queue
{private:
listec *curr, / / поля класса - указатели на текущий,
*first, / / первый
*last; / / и последний элементы класса
public:
queue(){curr=first=last=NULL; } // конструктор класса
void add(String fio,int d); // функция добавления элемента в очередь
void del(); // функция удаления элемента из очереди
AnsiString view(); // функция просмотра содержимого очереди
};
29
// реализация функциии добавления элемента в очередь
void queue::add(String fio,int d)
{ curr=new listec;
curr->num=d;
curr->Fio=fio;
curr->next=0;
if (first==0) first=curr; else last->next=curr;
last=curr;
}
// реализация функциии удаления элемента из очереди
void queue::del()
{ curr=first;
if (first==0){ShowMessage("Нет ничего!");return;}
first=first->next;
delete curr;
}
// реализация функциии просмотра содержимого очереди
AnsiString queue::view()
{AnsiString s="";
if(curr==0){ShowMessage("Нет ничего!");s="";return s;}
while (curr!=0)
{s=s+curr->Fio+" "+IntToStr(curr->num)+"\r\n";
curr=curr->next; }
return s;
}
CMyClass::CMyClass()// Конструктор
{ MyInt = 10; // На этапе инициализации объекта класса CMyClass
// переменной MyInt этого объекта присваивается значение 10
point = new int; // Выделение памяти по целое число для указателя
*point = 20; // Запись в выделенную память числа 20
}
CMyClass::~CMyClass()// Деструктор
{ MyInt = 0; // Объект класса CMyClass фактически прекратил своё
// существование,но мы присвоим переменной MyInt значение 0
Файл Unit2.h
class matr / / Объявление класса
{ float *b; / / указатель на матрицу
float *c; / / / /указатель на вектор
int n; / /указатель на размер матрицы
public:
matr( float *ib, int in,float *ic); / /конструктор
void vmatr(float *b, int n, floa *c); / /вычисление элементов матрицы
void vect(float *b,int n, float *c); / / вычисление элементов вектора
34
float func(float *b, int n, float *c); / / вычисление скаляра
};
Файл Unit2.cpp
#pragma hdrstop
#include <Math.h>
#include "Unit2.h"
#pragma package(smart_init)
/ / реализация конструктор
matr::matr(float *ib, int in,float *ic)
{ b=ib; n=in; c=ic;}
/ /вычисление элементов матрицы
void matr::vmatr(float *u, int n, float *c)
{for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
*(u+i*n+j)=2.5*pow((i+j+1),1./3)+4*(i+j+1)/(2+pow((j+1),2));
}
/ / вычисление элементов вектора
void matr::vect(float *b, int n, float *c )
{
float s;
for(int i=0;i<n;i++)
{s=0;
for(int j=0;j<n;j++)
s=s+*(b+i*n+j);
*(c+i)=s;
}
}
/ / вычисление скаляра
float matr::func(float *b, int n, float *d)
{
float s=0;
for(int i=0;i<n;i++)
s=s+c[i];
return s;
}
Главный модуль − Unit1.cpp
#include <vcl.h>
#pragma hdrstop
#include <Math.h>
#include "Unit1.h"
#include "Unit2.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
35
: TForm(Owner)
{
}
//------кнопка «Вычисление» ----------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int k=4;
float *a=new float [k*k]; / / объявление динамической матрицы a
float *C=new float [k]; / / объявление динамического вектора C
matr A(a,k,C); / / создание объекта класса − матрица A
A.vmatr(a,k,C); / / Вычичсление значений матрицы
/ / Вывод значений матрицы
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
SG1->Cells[j+1][i+1]=FloatToStrF(*(a+i*k+j),ffFixed,5,3);
/ / Вывод значений вектора C
A.vect (a,k,C);
for(int i=0;i<k;i++)
SG2->Cells[i][1]=FloatToStrF(*(C+i),ffFixed,5,3);
/ / Вычисление и вывод значений скаляра z
float z=A.func(a,k,C);
Edit2->Text=FloatToStr(z);
delete []a;
delete []C;
}
//------------ кнопка «Очистка» компонентов формы----------------
void __fastcall TForm1::Button7Click(TObject *Sender)
{
AnsiString s="";
s=s+" "+""+" "+""+" "+""+" ";
SG2->Rows[1]->DelimitedText=s;
for(int i=1;i<=4;i++)
SG1->Rows[i]->DelimitedText=s;
Edit2->Text="";
}
//---------кнопка «Выход»----------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{ Close();}
Форма проекта с результатами имеет вид:
36
}
37
Л а б о р а т о р н а я р а б о т а № 2.1
Контрольные вопросы
Лабораторное задание
1 Базовый уровень
Для всех вариантов заданий создать класс с указанными в таблице 1.1 (ко-
лонка 2) полями и тремя методами:
− конструктор для инициализации объекта;
− функция формирования строки с информацией об объекте;
− функция обработки значений полей по индивидуальному варианту.
38
В основной программе вводить значения полей каждого объекта из компо-
нентов Edit и выводить результаты в компонент Memo. Индивидуальные вари-
анты заданий приведены в таблице 1.1.
№
вар. Класс и его поля Функция обработки полей
1 Денежные купюры: номинал (1, 2, 5, 10 Вычислить сумму купюр
и т.д.) и количество
2 Монеты: номинал(1, 2, 5, 10 и т.д.) и Вычислить сумму монет
количество
3 Товар: цена и количество Вычислить общую стои-
мость товара
4 Продукты питания: калорийность 100 Вычислить общую кало-
г и вес продукта в граммах рийность продукта
5 Диапазон вещественных чисел: левая и Квадрат длины диапазона
правая границы диапазона
6 Время: минуты и секунды Вычислить общее количе-
ство секунд
7 Время: часы и минуты Вычислить общее количе-
ство минут
8 Катеты прямоугольного прямоуголь- Вычислить площадь прямо-
ника: вещественные числа к1 и к2 угольного треугольника
9 Параметры движения: скорость дви- Вычислить пройденное рас-
жения (м/cек) и время движения в ми- стояние (в метрах)
нутах
10 Катеты прямоугольного прямоуголь- Вычислить длину гипотену-
ника: вещественные числа а1 и а2 зы прямоугольного тре-
угольника
11 Параметры трапеции: верхнее и ниж- Вычислить полусумму ос-
нее основание трапеции нований трапеции
12 Катеты прямоугольного прямоуголь- Вычислить тангенс угла α ,
ника: вещественные числа р1 и р2 противолежащего второму
катету прямоугольного тре-
угольника
13 Пара вещественных чисел: z1 и z2 Вычислить полуразность
чисел
14 Пара вещественных чисел: р1 и р2 Вычислить корень квадрат-
ный из произведения чисел
15 Пара целых чисел: x и y Вычислить целую часть от
деления х на y
16 Пара целых чисел: a и b Вычислить квадрат мень-
шего из чисел
39
№
вар. Класс и его поля Функция обработки полей
17 Пара целых чисел: n и m Вычислить куб большего из
чисел
18 Телефонный разговор: продолжитель- Вычислить общую стои-
ность телефонного разговора в мину- мость разговора
тах и стоимость одной минуты разго-
вора
19 Точка на плоскости: координаты точки Определить периметр пря-
на плоскости (по горизонтали и верти- моугольника, ограниченно-
кали) го координатами точки и
осями Ox и Oy
20 Два вещественных числа: a и b Вычислить разность квад-
ратов чисел a2 – b2
21 Два вещественных числа: a и b Вычислить сумму квадра-
тов чисел a2 + b2
22 Точка на плоскости: координаты точки Определить площадь пря-
на плоскости (по горизонтали и верти- моугольника, ограниченно-
кали) x1 и y1 го координатами точки и
осями Ox и Oy
23 Точка на плоскости: координаты точки Вычислить расстояние от
на плоскости (по горизонтали и верти- точки до начала координат
кали) x1 и y1
24 Параметры работы: количество часов Общая стоимость работы
работы и тариф оплаты за час работы
25 Дуга: радиус окружности и угол в ра- Вычислить длину дуги
дианах
26 Цилиндр: радиус окружности основа- Вычислить площадь по-
ния и высота цилиндра верхности цилиндра
3 Высокий уровень
2 НАСЛЕДОВАНИЕ КЛАССОВ
Класс – параллелепипед
para p2;
Memo1->Lines->Add("Периметр прямоугольника="+FloatToStr(2*p2.sum()));
rectangle b(StrToFloat(Edit1->Text),StrToFloat(Edit2->Text));
Memo1->Lines->Add("Площадь прямоугольника="+FloatToStr(b.area()));
cylinder c(StrToFloat(Edit3->Text),StrToFloat(Edit4->Text));
Memo1->Lines->Add("Поверх. цилиндра="+FloatToStr(c.area()));
paral d(StrToFloat(Edit1->Text),StrToFloat(Edit2->Text),10);
Memo1->Lines->Add("Поверхн. параллелипипеда="+FloatToStr(d.area()));
}
Форма проекта с результатами вычислений имеет вид:
51
Пример 2.3 Создадим класс «матрица», полями которой является указа-
тель на квадратную матрицу размером nхn. Метод этого класса транспонирует
исходную матрицу. На базе этого класса создадим производный класс (пото-
мок), функции которого вычисляют евклидову норму (корень квадратный из
суммы квадратов элементов матрицы) и заменяют элементы первого столбца
матрицы на суммы элементов строк.
Текст программы
// Описание базового класса
class matr
{protected:
int *b; / / объявление динамической матрицы b
int n; / / размер матрицы
public:
matr( int *ib, int k);
void transp(int *u,int k);
};
// ---------реализация конструктора---------------------------------------------------
matr:: matr( int *ib, int k)
{b=ib; n=k;}
// Конструктор потомка
matrchild::matrchild(int *ib, int k):matr(ib,k){}
// Функция потомка − вычисление евклидовой нормы матрицы
float matrchild::norm()
{
int i,j,s=0;
52
for(i=0;i<n;i++)
for(j=0;j<n;j++)
s=s+pow(*(b+n*i+j),2);
return sqrt(s);}
// -------------Кнопка «Транспонировать»-----------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{ int m=StrToInt(Edit1->Text);
int *x; int i,j;
x=(int*)malloc(m*m*sizeof(int));
for(i=0;i<m;i++)
for(j=0;j<m;j++)
*(x+i*m+j) =StrToInt(StringGrid1->Cells[j+1][i+1]); //
matr ob1(x,m); // объект − родитель
ob1.transp(x,m); // вычисление по методу объекта-родителя
for(i=0;i<m;i++)
for(j=0;j<m;j++)
StringGrid2->Cells[j+1][i+1]=IntToStr(*(x+i*m+j));
}
Класс – матрица
Класс – вектор
Класс – скаляр
//--------Кнопка «Выход»---------------
void __fastcall TForm1::Button4Click(TObject *Sender)
60
{
Close();
}
//--------Кнопка «Очистка »---------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
AnsiString s="";
s=s+" "+""+" "+""+" "+""+" ";
SG2->Rows[1]->DelimitedText=s;
for(int i=1;i<=k;i++)
SG1->Rows[i]->DelimitedText=s;
Edit2->Text="";
}
Л а б о р а т о р н а я р а б о т а № 2.2
Контрольные вопросы
Лабораторное задание
2 Средний уровень
3 Высокий уровень
3 ПОЛИМОРФИЗМ
Текст программы:
class TParent // базовый класс
{ public:
virtual void Draw();
};
class TChild1 : public TParent // класс− первый наследник
{ public: void Draw();
};
class TChild2 : public TParent // класс − второй наследник
{ public: void Draw();
};
void TParent:: Draw()// метод базового класса
{ Form1->Memo1->Lines->Add (" Это базовый класс"); }
В отдельных файлах описать классы как 1-го, так и 2-го уровня (размеще-
ние в отдельных файлах − см. пример 1.3), инициализировать их и вывести ин-
формацию о них на форму.
#ifndef Unit2H
#define Unit2H
#include <vcl.h> // добавить библиотеку компонентов vcl.h
//-----------------------------------------------------------------------------------
class Tvrach {
private:
int kolpr;
AnsiString FIO;
protected:
int kolp;
virtual float rachest(void); // функция вычисления качества с перекрытием
public:
Tvrach (AnsiString iFIO, int ikolp, int ikolpr) ; // конструктор
AnsiString Info(void); // без перекрытия
};
#endif
#endif
#pragma hdrstop
#include "Unit3.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
Текст программы:
Л а б о р а т о р н а я р а б о т а № 2.3
Контрольные вопросы
Лабораторное задание
Q = 0,1*мощность*число мест
16 Студент: P: число оценок «три»
- фамилия,
- число экзаменов,
- число оценок «пять». Qp = Q − 0,5*Р
Q = число оценок «пять» / число экзаме-
нов
17 Фирма: P: инвестиции в фирму (тыс. $)
- название,
- доход (тыс. $ ), Qp = Р3 + Q
- рейтинг (в баллах).
Q = доход *рейтинг
18 Военный корабль: P: крейсерская скорость
- название, (в морских узлах)
- длина,
- число пушек главного калибра. Qp = 0,25*Q + Р
Q = (число пушек) / длина
19 Коробка спичек: P: средний % бракованных
- фирма изготовитель, спичек в коробке
- число спичек в коробке,
- время горения одной спички (с). Qp = ( 100−Р) * Q / 100
Q = (число спичек)*время
2 Средний уровень
TObject
TPersistent
TComponent
Если в разделах read или write этого объявления записано имя поля, зна-
чит предполагается прямое чтение или запись данных.
Если в разделе read записано имя метода чтения, то чтение будет осуще-
ствляться только функцией с этим именем. Имя функции чтения принято начи-
нать с префиксом Get, после которого следует имя свойства.
Если в разделе write записано имя метода записи, то запись будет осуще-
ствляться только процедурой с этим именем. Имя процедуры записи принято
начинать с префикса Set, после которого следует имя свойства.
Если раздел write отсутствует в объявлении свойств, значит это свойство
только для чтения. Для директивы запоминания чаще всего используется ди-
ректива следующего вида:
default <значение по умолчанию>
#ifndef EdH
#define EdH
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
101
class PACKAGE TEd : public TEdit
{
private:
bool FEnabfloat;
void __fastcall SetNumb(float f);//для изменения содержимого TEd
float __fastcall GetNumb(void); // для ввода данных в TEd
protected:
public:
__fastcall TEd(TComponent* Owner);
#include <vcl.h>
#pragma hdrstop
#include "Ed.cpp" //подключаем модуль нового компонента
#include "Unit1.h"
//----------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//----------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{ }
#endif
#include <vcl.h>
#pragma hdrstop
#include "uSEd.h"
#pragma package(smart_init)
//----------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
105
static inline void ValidCtrCheck(TSEd *)
{
new TSEd(NULL);
}
//----------------------------------------------------------------
__fastcall TSEd::TSEd(TComponent* Owner)
: TEdit(Owner)
{ w=1; }
// Тестирование компонента
TSEd *DSEd;
#ifndef SGH
#define SGH
//----------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <Grids.hpp>
//----------------------------------------------------------------
class PACKAGE TSG : public TStringGrid
{
private:
bool flag;
AnsiString Name;
protected:
public:
__fastcall TSG(TComponent* Owner);
DYNAMIC void __fastcall KeyDown(Word &Key,
Classes::TShiftState Shift);
DYNAMIC void __fastcall Click(void);
__published:
};
//----------------------------------------------------------------
#endif
#include <vcl.h>
#pragma hdrstop
#include "SG.h"
#pragma package(smart_init)
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
107
static inline void ValidCtrCheck(TSG *)
{
new TSG(NULL);
}
__fastcall TSG::TSG(TComponent* Owner)
: TStringGrid(Owner)
{ flag=true; Name="Сетка";
}
void __fastcall TSG::KeyDown(Word &Key,
Classes::TShiftState Shift)
{ if (Key==VK_ESCAPE)
for (int i=0; i<RowCount;i++)
for (int j=0; j<ColCount; j++)
Cells[j][i]="";
if (Key==VK_F11)
for (int i=0; i<RowCount;i++)
for (int j=0; j<ColCount; j++)
Cells[j][i]=IntToStr(random(20));
if (Key==VK_F12)
ShowMessage(Name +" "+IntToStr(RowCount)+" "+
IntToStr(ColCount));
TStringGrid::KeyDown(Key, Shift);
}
Тестирование компонента
#include "SG.cpp"
TSG *SGt;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
SGt=new TSG(Form1);
SGt->Parent=Form1;
108
SGt->Left=20;
SGt->Top=20;
SGt->FixedRows=0;
SGt->FixedCols=0;
SGt->RowCount=4;
SGt->ColCount=5;
SGt->Options<<goEditing<<goTabs;
for (int j=0;j<SGt->ColCount;j++)
for (int i=0;i<SGt->RowCount;i++)
SGt->Cells[j][i]=IntToStr(random(20)-10);
}
а б в
Рис. 4.2. Результаты работи с компонентом SG:
а) при нажатии клавиши <F11> ;
б) при щелчке левой клавишей мыши;
в) при нажатии клавиши <Esc>.
рragma hdrstop
#include "Mem.h"
#pragma package(smart_init)
#include "Mem.cpp"
TMem *Mm;
stRectangle – прямоугольник;
stRoundRect – прямоугольник со скругленными углами;
stEllipse – эллипс;
stSquare – квадрат;
stRoundSquare – квадрат со скругленными углами;
stCircle – круг.
#ifndef ShapH
#define ShapH
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <ExtCtrls.hpp>
class PACKAGE TShap : public TShape
{private:
bool FOnOff; //разрешает переключение цветов
TColor FOnColor; // цвет первого плана
TColor FOffColor; // цвет второго плана
void __fastcall SetOnOff(const bool Value); //переключение цветов
void __fastcall SetOnColor(const TColor OnColor); //установка цвета
//первого плана
void __fastcall SetOffColor(const TColor OffColor); //установка цвета
//второго плана
protected:
public:
__fastcall TShap(TComponent* Owner);
__published:
__property bool ShapOn={read=FOnOff, write=SetOnOff} ;
};
#endif
#include <vcl.h>
#pragma hdrstop
#include "Shap.h"
#pragma package(smart_init)
static inline void ValidCtrCheck(TShap *)
{
new TShap(NULL);
}
__fastcall TShap::TShap(TComponent* Owner)
: TShape(Owner)
{ // начальные значения для фигуры
Width=35;
Height=35;
FOnColor=clLime;
112
FOffColor=clRed;
FOnOff=false;
Shape=stEllipse;
Pen->Color=clBlack;
Pen->Width=2;
Brush->Color=FOffColor;
}
// Тестирование компонента
#include "Shap.cpp"
//
TShap *Sh;
Тестирование компонента
#include "Shap2.cpp"
TShap2 *Sha;
int tt=0;
Контрольные вопросы
Литература
Предисловие………………………………………………………………..…..3
1 ЭЛЕМЕНТЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО
ПРОГРАММИРОВАНИЯ……………………………………………………5
Лабораторная работа № 2.1 Программирование создания
классов и их объектов….…...……………………………………….……..37
3 ПОЛИМОРФИЗМ …………………….…………………………..…………71
Лабораторная работа № 2.3 Программная реализация свойства
полиморфизм ….........................................................................................…84
Навчальне видання
Технології програмування
МОДУЛЬ № 1
Частина 2
Об’єктно-орієнтоване програмування
Методичні вказівки
до лабораторних й практичних занять