
C _Учебник_МОНУ
.pdfОб’єктно-орієнтоване програмування |
509 |
|
|
тить такі методи: конструктор за замовчуванням, конструктор з двома параметрами; podatok() – метод який обчислює податок працівника за встановленим правилом; zarplatnia() – метод який обчислює “чисту” зарплатню працівника.
Примітка. Якщо серед методів класу є такі, що мають тип AnsiString, наприклад,
AnsiString info()
{ return " Зарплатня =" + FloatToStr(zarplatnia()); }
тоді першою у файлі необхідно записати директиву
#include <vcl.h>
Запишемо у файлі Рrac.cpp визначення (реалізацію) методів класу podatok() та zarplatnia() (після всіх стандартних директив файла):
Файл Рrac.cpp
#pragma hdrstop
#include "Рrac.h" // Автоматичне долучення файлів визначення класу // Реалізація методу обчислювання податку
double pracivnik::podatok()
{double nal; switch(vid)
{case 0: if(oklad<=300) nal=0; else nal=oklad*0.15; break; case 1: nal=oklad*0.2;
}
return nal;
}
// Реалізація методу обчислювання зарплатні double pracivnik::zarplatnia()
{ return oklad - podatok();
}
Запишемо у головному файлі проекту Unit1.cpp код програми для кнопки “Обчислити” та долучимо до нього файл визначення класу Prac.h.
Головний файл проекту Unit1.cpp
#include <vcl.h>
// Долучення файла оголошення та визначення методів класу
#include "Prac.h"
#pragma hdrstop #include "Unit1.h"
//--------------------------------------------------------
#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1;
//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}

Об’єктно-орієнтоване програмування |
511 |
||
|
|
|
|
void del(); |
|
// Вилучення елемента з черги |
|
AnsiString view(); |
// Переглядання змісту черги |
|
|
}; |
|
|
|
// Реалізація функції долучення елемента до черги |
|
||
void queue::add(String fio,int d) |
|
||
{ curr=new listec; |
// Виділення пам‟яті під новий елемент черги |
|
|
curr->Fio=fio; |
// Занесення до нового елемента прізвища |
|
|
curr->num=d; |
// Занесення до нового елемента значення балу |
|
|
curr->next=0; // Після нового елемента інших елементів покищо немає |
|
||
if (first==0) |
// Якщо черги ще нема, |
|
|
first=curr; |
// то новий елемент стає першим, |
|
|
else |
// інакше елемент долучається після останнього, |
|
|
last->next=curr; |
// записуючи в last адресу нового елемента |
|
|
last=curr; |
// Тепер новий елемент стає останнім |
|
|
} |
|
|
|
// Реалізація функції вилучення першого елемента з черги |
|
||
void queue::del() |
|
|
|
{ curr=first; |
|
|
|
if (first==0) |
// Якщо черга є порожня, |
|
|
{ ShowMessage("Черга порожня!"); // виводиться повідомлення |
|
||
return; |
// і виконання переривається |
|
|
} |
|
|
|
first=first->next;// first указує на наступний елемент |
|
||
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;
}
queue stt; // Створення об‟єкта класу
// Кнопка долучання до черги нового елемента (інформації про студента) void __fastcall TForm1::Button1Click(TObject *Sender)
{String fio=Edit1->Text;
int d=StrToInt(Edit2->Text); stt.add(fio,d); Edit1->Text="";
Edit2->Text=""; Edit1->SetFocus();
}

Об’єктно-орієнтоване програмування |
513 |
|
|
У попередніх програмах об‟єкти створювалися після їхнього оголошення. По завершенні програми C++ автоматично викликав деструктор для кожного об‟єкта, хоча його не було явно визначено у програмі.
Деструктор, окрім деініціалізації об‟єктів, може виконувати деякі дії, наприклад, виведення остаточних значень елементів даних класу, що буває зручно при налагодженні програми. Як приклад, визначимо клас worker з деструктором та конструктором:
class worker
{ private:
char name[64] ; long worker_id; float salary;
public: // Загальнодоступні методи класу worker(char *iname, long іworker_id, float isalary); // конструктор
void ~worker(void); // Деструктор
void show_worker(void); // Функція виведення інформації
};
Реалізація деструктора для класу worker (поза класом):
void worker::~worker(void)
{ cout << "Знищення об’єкта для " << name << endl; }
Цей деструктор у консольному режимі виведе на екран значення елемента класу name та повідомлення про те, що C++ знищує цей об‟єкт. Наприклад, створимо об‟єкт для визначеного вище класу:
void main(void)
{ worker worker("Василенко", 777, 10101.0); worker.show_worker();
}
У результаті виконання цієї програми на екрані побачимо:
Прізвище: Василенко Код робітника: 777 Зарплатня: 10101.00
Знищення об’єкта для Василенко
Явно розміщувати деструктор у класі треба у разі, якщо об‟єкт містить вказівники на пам‟ять, виділену динамічно, – інакше при знищуванні об‟єкта пам‟ять, на яку посилались його поля-вказівники, не буде позначено як звільнену.
сlass CMyClass
{ public:
CMyClass(); |
//Конструктор класу CMyClass |
~CMyClass(); |
//Деструктор класу CMyClass |
private: |
|
int MyInt; |
//Змінна типу int (ціле число) |
int *point; |
//Змінна типу вказівник на int (ціле число) |
}; |
|

Об’єктно-орієнтоване програмування |
515 |
||
|
|
|
|
Файл Unit1. cpp |
|
|
|
//--------- Відгук на кнопку «Об‟єкти класу» -------------- |
|
||
void __fastcall TForm1::Button1Click(TObject *Sender) |
|
||
{ resistor a11; |
// Створення об‟єкта класу a11 конструктором 1 |
||
float ra1=a11.comr(); // Обчислення сумісного опору для об‟єкта a11 |
|
||
// Виведення результатів для об‟єкта a11 |
|
|
|
Memo1->Lines->Add(a11.Info()+" |
r_a11="+FloatToStr(ra1)); |
|
|
a11.~ resistor(); |
// Знищення об‟єкта a11 деструктором |
|
|
resistor a12(40); |
// Створення об‟єкта класу a12 конструктором 2 |
||
float ra2=a12.comr(); // Обчислення сумісного опору для об‟єкта a12 |
|
||
// Виведення результатів для об‟єкта a12 |
|
|
|
Memo1->Lines->Add(a12.Info()+" |
r_a12="+FloatToStr(ra2)); |
|
|
resistor a13(20,20); |
// Створення об‟єкта класу a13 конструктором 3 |
||
float ra3=a13.comr(); // Обчислення сумісного опору для об‟єкта a13 |
|
||
// Виведення результатів для об‟єкта a13 |
|
|
|
Memo1->Lines->Add(a13.Info()+" |
r_a13="+FloatToStr(ra3)); |
|
|
} |
|
|
|
Результати роботи програми – значення загального опору двох паралельних резисторів для трьох об‟єктів, створених за різними конструкторами та з явним використанням деструктора, – наведено на зображенні форми проекту:
Як бачимо, після роботи з першим об‟єктом (a11) викликається функ- ція-деструктор, яка знищує об‟єкт та виводить повідомлення про цю дію. Наприкінці програми деструктор автоматично звільнює пам‟ять від усіх об‟єктів програми (у зворотному порядку), у тому числі повторює повідомлення про об‟єкт a11.
14.7 Успадкування
Успадкування (inheritance) – це механізм, за допомогою якого один об‟єкт може набувати властивості іншого. Точніше, об‟єкт може успадковувати основні властивості іншого об‟єкта та набувати нових рис, які характерні лише для нього. Успадкування є дуже важливим, оскільки воно дозволяє підтримувати принцип ієрархії класів (hierarchical classification). Наприклад, клас мобільних


Об’єктно-орієнтоване програмування |
517 |
|
|
Для створювання похідного класу використовують ключове слово class, після якого записують ім‟я нового класу, двокрапку (:), ключ доступу класу (public, private, protected), а потім зазначають ім‟я батьківського класу:
сlass
<ім‟я_похідного_класу>:[<ключ_доступу>]<ім‟я_батьківського_класу> { <тіло_класу> };
Вище розглядались лише специфікатори доступу private (закритий) та public (відкритий), які застосовуються до полів класу. Однак члени базового класу, оголошені як private, у похідному класі є недоступні незалежно від ключа доступу. Звертання до них може відбуватися лише через методи базового класу. Для базових класів можливе використання ще одного специфікатора – protected (захищений), який для поодиноких класів, що не входять до ієрархії, означає те ж саме, що й private.
Ключ доступу public означає, що всі відкриті й захищені члени базового класу стають такими для похідного класу. Ключ доступу private означає, що всі відкриті й захищені члени базового класу стають закритими членами для похідного класу. Ключ доступу protected означає, що всі відкриті й захищені члени базового класу стають захищеними членами похідного класу.
Розглянемо успадкування класів на прикладі.
Приклад 14.5. Створити клас – “два дійсних числа”, які можуть відображати значення висоти та ширини геометричної фігури. На базі цього класу створити два похідні класи: “прямокутник”, який обчислює площу прямокутника, та “циліндр”, який обчислює площу бокової поверхні циліндра. Для класу “прямокутник” створити похідний клас “паралелепіпед”, який обчислює об‟єм паралелепіпеда з використання параметра – значення висоти. Ієрархію цих класів наведено на рис 14.2.
Клас – два дійсних числа
Клас – прямокутник |
|
Клас – циліндр |
|
|
|
Клас – паралелепіпед
Рис. 14.2. Ієрархія класів для прикладу 14.5
Код програми:
#include <vcl.h> #pragma hdrstop #include "Unit1.h"
//-------------------------------------------------------------
#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1;
//-------------------------------------------------------------