ТА_Методички / Lec2_10
.pdf// Клас house є похідним від класу building class house : public building
{
int bedrooms; int baths;
public:
void set_bedrooms(int num) ; int get_bedrooms ();
void set_baths(int num); int get_baths();
};
Зверніть увагу на те, як відбувається спадкування властивостей класу building. У загальному випадку похідний клас оголошується в такий спосіб.
class похідний_клас : специфікатор_доступу базовий_клас
{
// тіло нового класу
}
Тут специфікатор_доступу вказувати необов'язково. Цей параметр може приймати три значення: public, private або protected.
11/33
Поки будемо вважати, що всі похідні класи використовують відкрите спадкування. Ключове слово public означає, що всі відкриті члени базового класу стаютьвідкритими членами похідного класу.
Отже, відкриті члени класу building стають відкритими членами похідного класу house і доступні функціям-члена класу house, начебто вони оголошені безпосередньо всередині похідного класу. Однак функції-члени класу house не мають доступу до закритих членів класу building.
Це дуже важливий момент. Незважаючи на те що клас house є спадкоємцем класу building, він має доступ лише до відкритих членів класу building. Таким чином, спадкування не дозволяє порушити принципи інкапсуляції інформації, покладеного в основу об’єкт но-орієнтованого програмування.
Похідний клас має прямий доступ як до своїх членів, так і до відкритих членів базового класу.
12/33
Розглянемо програму, що демонструє механізм спадкування. Вона створює два класи, похідних від класу building: класи house і school.
#include <iostream> using namespace std; class building
{
int rooms; int floors; int area;
public:
void set_rooms(int num); int get_rooms();
void set_floors(int num); int get_floors();
void set_area (int num); int get_area();
}
// Клас house є похідним від класу building class house: public building
{
int bedrooms; int baths;
13/33
public:
void set_bedrooms(int num); int get_bedrooms();
void set_baths(int num); int get_baths();
}
// Клас school також є похідним від класу building class school: public building
{
int classrooms; int offices;
public:
void set_classrooms(int num); int get_classrooms();
void set_offices(int num); int get_offices();
};
// Функції присвоєння значень
void building::set_rooms(int num)
{
rooms = num; }
void building::set_floors(int num) { floors = num;
}
14/33
void building::set_area(int num)
{
area = num; }
// Функції взяття (витягування) значень int building::get_rooms()
{
return rooms;
int building::get_floors() { return floors;
}
int building::get_area() {return area;
}
// Всі перераховані функції належать до класу building (використано оператор задання області видимості ::)
void house::set_bedrooms(int num) {bedrooms = num;} void house::set_baths(int num) {baths = num;}
int house::get_bedrooms() {return bedrooms;} int house::get_baths() {return baths;}
15/33
void school::set_classrooms(int num) {classrooms = num;} void school::set_offices(int num)
{ offices = num; }
int school::get_classrooms() { return classrooms; }
int school::get_offices() { return offices;}
int main()
house h; school s; // Оголошеноекземплярикласівhouse іschool відповідно h.set_rooms(12); h.set_floors(3);
h.set_area(4500) ; h.set_bedrooms(5); h.set_baths(3);
cout << "У будинку " << h.get_bedrooms(); cout << " спалень \n"; s.set_rooms(200);
s.set_classrooms(180); s.set_offices(5) ; s.set_area(25000);
cout << "У школі " << s.get_classrooms(); cout << " класних кімнат \n";
cout << "Її площа дорівнює " << s.get_area(); return 0;
}
16/33
Результат роботи цієї програми наведений нижче:
Убудинку 5 спалень
Ушколі 180 класних кімнат Її площа дорівнює 25000
Як бачимо, основна перевага механізму спадкування полягає в тім, що можна спочатку створити загальну класифікацію, а потім на її основі розробити уточнюючі класи. Таким чином, кожний об'єкт може точно представляти свій власний підклас.
У книгах про мову C++ відношення спадкування часто описують за допомогою термінів базовий клас і похідний клас. Однак поряд з ними часто згадуються терміни
предокіспадкоємець. Крімтого, можназустрітипоняттясуперкласіпідклас.
Крім можливості створювати ієрархічну класифікацію, спадкування забезпечує підтримку динамічного поліморфізму за допомогою механізму віртуальних функцій.
17/33
4. Конструктори й деструктори
Дуже часто деяка частина об'єкта перед його першим використанням повинна бути ініціалізована. Наприклад, повернемося до опису класу stack. Перед першим використанням об'єкта цього класу змінної tos варто присвоїти число 0. Для цього призначена функція init(). Оскільки ініціалізація об'єктів дуже розповсюджена вимога, у мові C++ передбачений особливий механізм, що дозволяє ініціалізувати об'єкти в момент їхнього створення. Ця автоматична ініціалізація здійснюється конструктором.
Конструктор — це особлива функція, що є членом класу. Її ім'я повинне збігатися з ім'ям класу. Наприклад, клас stack можна модифікувати, передбачивши в ньому конструктор.
// Клас stack з конструктором. class stack {
int stck[SIZE]; int tos; public:
stack(); // Конструктор void push(int i);
int pop(); };
18/33
Зверніть увагу на те, що в оголошенні конструктора stack() не зазначений тип значення, що повертається, оскільки в мові C++ конструктори в принципі не можуть повертати значення.
Код конструктора stack () може виглядати так:
// Конструктор класу stack stack::stack ()
{
tos = 0;
cout << "Стек ініціалізовано \n";
}
Врахуйте, що повідомлення "Стек ініціалізовано" просто ілюструє роботу конструктора. На практиці конструктори найчастіше нічого не вводять і не виводять, вони просто виконують різні види ініціалізації.
Конструктор автоматично викликається в момент створення об'єкта, тобто при його оголошенні. Отже, оголошення об'єкта в мові C++ - це не пасивний запис, а активний процес. У мові C++ оголошення є виконуваним оператором.
19/33
Це розходження носить зовсім не академічний характер. Код, за допомогою якого конструюється об'єкт, може бути досить важливим. Для глобальних і статичних локальних об'єктів конструктори викликаються лише один раз. При оголошенні локальних об'єктів конструктори викликаються щораз при вході у відповідний блок.
Антиподом конструктора є деструктор. У багатьох ситуаціях об'єкт повинен виконати деяку дію або дії, які знищать його. Локальні об'єкти створюються при вході у відповідний блок, а при виході з нього вoни знищуються. При знищенні об'єкта автоматично викликається його деструктор. Для цього існує кілька причин. Наприклад, об'єкт повинен звільнити займану їм пам'ять або закрити файл, відкритий ним раніше.
У мові C++ ці дії виконує деструктор. Ім'я деструктора повинне збігатися з ім'ям конструктора, і перед ним ставиться знак ~ (тільда). Розглянемо клас stack, що містить конструктор і деструктор. (Врахуйте, що насправді клас stack не має потреби в деструкторі, тут він наведений як ілюстрація.)
// Оголошення класу stack class stack {
int stck[SIZE]; int tos; public:
20/33
