- •2. Інтегроване середовище розробки Delphi: призначення і загальний опис середовища
- •3. Загальна організація програми в Delphi
- •4. Деякі довідкові відомості для роботи у середовищі Delphi
- •Цикл (программирование)
- •[Править]Определения
- •[Править]Виды циклов [править]Безусловные циклы
- •[Править]Цикл с предусловием
- •[Править]Цикл с постусловием
- •[Править]Цикл с выходом из середины
- •[Править]Цикл со счётчиком
- •[Править]Совместный цикл
- •[Править]Досрочный выход и пропуск итерации
- •[Править]Досрочный выход из цикла
- •[Править]Пропуск итерации
- •[Править]Необходимость
- •[Править]Вложенные циклы
- •[Править]Циклы с несколькими охраняемыми ветвями [править]Цикл Дейкстры
- •[Править]Цикл «паук»
- •[Править]Интересные факты
- •3.1 Інкапсуляція
- •3.2 Класи, компоненти і об'єкти
- •3.3 Спадкоємство
- •3.4 Розробка класів
- •3.4.1 Оголошення базового класу
- •3.4.2 Конструктори і деструкції
- •3.4.3 Оголошення похідних класів
- •3.5 Поліморфізм
- •3.5.1 Віртуальні функції
- •3.5.2 Дружні функції
- •3.6.1 Компоненти
- •3.6.1.1 Оголошення компонентних класів
- •3.6.1.2 Оголошення властивостей
- •3.6.1.3 Оголошення обробників подій
- •3.6.1.4 Оголошення автоматизованих властивостей і методів
- •3.6.1.5 Швидкий виклик функцій
- •3.6.1.6 Розширені типи даних Delphi
3.4.3 Оголошення похідних класів
C++Builder дає можливість оголосити похідний клас, який успадковує властивості, дані, методи і події всіх своїх попередників в ієрархії класів, а також може оголошувати нові характеристики і перенавантажувати деякі з успадкованих функцій. Успадковувавши вказані характеристики базового класу, можна змусити породжений клас розширити, звузити, змінити, знищити або залишити їх без змін.
Спадкоємство дозволяє повторно використовувати код базового класу в екземплярах похідного класу. Концепція повторного використання має паралель в живій природі: ДНК можна розглядати як базовий матеріал, який кожна породжена істота повторно використовує для відтворення свого власного вигляду.
Лістинг 3.5 ілюструє узагальнений синтаксис оголошення похідного класу. Порядок перерахування секцій відповідає розширень привілеїв захисту і зон видимості укладених в них елементів: від найбільш обмежених до найдоступніших.
class className : [^спецификатор доступу;”] parentClass {
<0б'явленія дружніх класів>
private:
<приватні члени даних>
<приватні конструктори>
<приватні методи> protected:
<захищені члени даних>
<захищені конструктори>
<захищені методи> public:
<загальнодоступні властивості>
<загальнодоступні члени даних>
<загальнодоступні конструктори>
<загальнодоступна деструкція>
<загальнодоступні методи> _published:
<загальновідомі властивості>
<загальновідомі члени даних>
<Оголошення дружніх функцій>
Лістинг 3.5. Оголошення похідного класу.
Відзначимо появу нової секції з ключовим словом _published - доповнення, яке C++Builder вводить в стандарт ANSI C++ для оголошення загальновідомих елементів компонентних класів. Ця секція відрізняється від загальнодоступної тільки тим, що компілятор генерує інформацію RTTI про властивості, членів даних і методи об'єкту і C++Builder організовує передачу цій інформації Інспекторові об'єктів під час виконання програми. В розділі 6 ми зупинимося на цьому детальніше.
Окрім здатності виконувати своє безпосереднє завдання об'єктні методи отримують певні привілеї доступу до значень властивостей і даних інших класів.
Коли клас породжується від базового, всі його імена в похідному класі автоматично стають приватними за умовчанням. Але його легко змінити, вказавши наступні специфікатори доступу базового класу:
• private. успадковані (тобто захищені і загальнодоступні) імена базового класу стають недоступними в екземплярах похідного класу.
• public. Загальнодоступні імена базового класу і його попередників будуть доступними в екземплярах похідного класу, а всі захищені залишаться захищеними.
Можна породжувати класи, які розширюють можливості базового класу:
він цілком прийнятний для вас, проте містить функцію, що вимагає невеликого доопрацювання. Написання наново потрібної функції в похідному класі є марною тратою часу. Замість цього треба повторно використовувати код в базовому класі, розширюючи його настільки, наскільки це необхідно. Просто перевизначите в похідному класі ту функцію базового класу, яка вас не влаштовує. Так само можна створювати класи, які обмежують можливості базового класу: він цілком прийнятний для вас, але робить щось зайве.
Розглянемо застосування методик розширення і обмеження характеристик на прикладі створення різновидів об'єкту кнопки - типових похідних класів, що отримуються при спадкоємстві базового компонента TButtonControl із Бібліотеки Візуальних Компонентів C++Builder. Кнопки різного вигляду часто з'являтимуться в діалогових вікнах графічного інтерфейсу ваших програм.
Мал. 3.1 показує, що базовий клас TButtonControl здатний за допомогою батьківського методу Draw відображати кнопку у вигляді двох вкладених прямокутників: зовнішньої рамки і внутрішньої закрашеної області.
Щоб створити просту кнопку без рамки (мал. 3.2), потрібно побудувати похідний клас SimpleButton, використавши як батьківського TButtonControl, і перенавантажувати метод Draw з обмеженням його функціональності (Лістинг 3.6)
class SimpleButton: public : TButtonControl { public:
SimpleButton(int x int y) ;
void Draw() ;
-SimpleButton() { }
};
SimpleButton::SimpleButton(int x int y) :
TbuttonControl(x, у) { }
void SimpleButton::Draw()
{ ; outline->Draw();
}
Лістинг 3.6. Обмеження характеристик базового класу.
Єдине завдання конструктора об'єкту для SimpleButton - викликати базовий клас з двома параметрами. Саме перевизначення методу SimpleButton: : Draw ( ) запобігає виведенню рамки кнопки, що обводить (як відбувається в батьківському класі). Природно, щоб змінити код методу, треба вивчити його з початкового тексту базового компоненту TButtonControl.
Тепер створимо кнопку з назвою пояснення (мал. 3.3). Для цього потрібно побудувати похідний клас TextButton з базового TButtonControl, і перенавантажувати метод Draw. Рис. 3.3. Кнопка з текстом, розширенням його функціональності.
Лістинг 3.7 показує, що об'єкт назви title класу Text створюється конструктором TextButton, а метод
SimpleButton:-.Draw () відображає його. :
class Text { public:
Text(int x, int у char* string) { } void Draw() { } };
class TextButton: public : TButtonControl {
Text* title;
public:
TextButton(int x int у, char* title);
void Draw();
-TextButton() { } );
TextButton::TextButton(int x int у, char* caption)
TButtonControl(x, у){
title = new Text(x, у, caption);
}
void TextButton::Draw () {
TextButton::Draw() ;
title->Draw() ;
}
Лістинг 3.7. Розширення характеристик базового класу.
На закінчення розділу з викладом методики розробки базових і похідних класів приводиться фрагмент C++ програми (Лістинг 3.8), в якій оголошена ієрархія класів двох простих геометричних об'єктів: кола і циліндра.
Програма складена так, щоб внутрішні значення змінних градіусів кола і h-висоти циліндра визначали параметри створюваних об'єктів. Базовий клас Circle моделює коло, а похідний клас Cylinder моделює циліндр.
class SimpleButton: public : TButtonControl { public:
SimpleButton (int x int y) ;
void Draw() ;
-SimpleButton() { } );
SimpleButton::SimpleButton(int x int y) :
TButtonControl(x, у) { }
I void SimpleButton::Draw()
I { i outline->Draw();
1 )
Лістинг 3.7 показує, що об'єкт назви title класу Text створюється конструктором TextButton, а метод
SimpleButton: : Draw () відображає його.
const double pi = 4 * atan(l);
class Circle { protected:
double r ;
public:
Circle (double rVal =0) : r(rVal){}
void setRadius(double rVal) { r = rVal; }
double getRadiusO { return r; } .double Area() { return pi*r*r; }
void showData() ;
};
class Cylinder : public Circle { protected:
double h;
public:
Cylinder(double hVal = 0 double rVal = 0)
: getHeight(hVal), Circle(rVal) { }
void setHeight(double hVal) { h = hVal; }
double getHeight() { return h; }
double Area() { return 2*Circle::Crea()+2*pi*r*h; }
void showData() ;
void Circle::showData() {
cout “ "Радіус кола = " “ getRadius() “ endl
“ "Площа круга = " “ Area O “ endl “ endl;
}
void Cylinder::showData()
{
cout “ "Радіус підстави = " “ getRadius() “ endl
“ "Висота циліндра = " “ getHeight() “ endl
“ "Площа поверхні = " “ Area () “ endl;
}
void main()
{
Circle circle(2);
Cylinder cylinder(10, 1);
circle.showData () ;
cylinder.showData() ;
Лістинг 3.8. Проста ієрархія класів кола і циліндра.
Оголошення класу Circle містить єдиний член даних r, конструктор і ряд методів. При створенні об'єкту конструктор ініціалізував член даних r початковим значенням радіусу кола. Відзначимо новий синтаксис конструктора: при виклику він може звернутися до конструктора базового класу, а також до будь-якого члена даних, вказаного після двокрапки. У нашому випадку член даних r "створюється" зверненням до нього з параметром rval і ініціалізувався нульовим значенням.
Метод setRradius встановлює, а getRadius повертає значення члена даних r. Метод Area повертає площа круга. Метод showData видає значення радіусу кола і площі круга.
Клас Cylinder, оголошений як похідний від Circle, містить єдиний член даних h, конструктор і ряд методів. Цей клас успадковує член даних г для зберігання радіусу підстави циліндра і методи setRadius і getRadius. При створенні об'єкту конструктор ініціалізував члени даних г і h початковими значеннями. Відзначимо новий синтаксис конструктора: у нашому випадку член даних h ініціалізувався значенням аргументу hVal, а член даних г - викликом конструктора базового класу Circle з аргументом rVal.
Функція setHeight встановлює, а getHeight повертає значення члена даних h. Circle::Area перенавантажує успадковану функцію базового класу, щоб тепер повертати площу поверхні циліндра. Функція showData видає значення радіусу підстави, висоти і площі поверхні циліндра.
Функція main створює коло circle класу Circle з радіусом 2 і циліндр cylinder класу Cylinder з висотою 10 і радіусом підстави 1, а потім звертається до showData для виведення параметрів створених об'єктів:
Радіус кола = 2 Площа круга = 12.566
Радіус підстави = 1 Висота циліндра = 10 Площа поверхні = 69.115