
- •Міністерство надзвичайних ситуацій України Львівський державний університет безпеки життєдіяльності Юрій грицюк, Тарас рак
- •Навчальний посібник
- •Потреба використання об'єктно-орієнтованого програмування
- •Поняття про об’єктно-орієнтований підхід до розроблення складних програм
- •Основні компоненти об’єктно-орієнтованої мови програмування
- •Поняття про універсальну мову моделювання
- •Базові поняття класу
- •Код програми 2.1. Демонстрація механізму оголошення класу та його застосування
- •Поняття про конструктори і деструктори
- •Особливості реалізації механізму доступу до членів класу
- •Класи і структури - споріднені типи
- •Об'єднання та класи - споріднені типи
- •Поняття про вбудовані функції
- •Inline int myClass::Put() return c;
- •Особливості організації масивів об'єктів
- •Особливості використання покажчиків на об'єкти
- •Поняття про функції-"друзі" класу
- •Код програми 3.1. Демонстрація механізму використання "дружньої" функції для доступу до закритих членів класу
- •Код програми 3.2. Демонстрація механізму використання "дружньої" функції для перевірки статусу кожного об'єкта
- •Void Run(); //Таймер відліку часу
- •Void timerClass::Run()
- •Int mainO
- •Особливості механізму динамічної ініціалізації конструктора
- •Int s; public:
- •Void Run(); //Таймер відліку часу
- •Void timerClass::Run()
- •Int mainO
- •Особливості механізму присвоєння об'єктів
- •Int а, ь; public:
- •Int mainO
- •Особливості механізму передачі об'єктів функціям
- •Void Fun(myClassobj)
- •Int mainO
- •Конструктори, деструктори і передача об'єктів
- •Void Get(myClass obj)
- •Int mainO
- •Потенційні проблеми, які виникають при передачі об'єктів
- •Int *р; public:
- •Void Get(myClass &obj) // Передача об'єкта за посиланням
- •Int mainO
- •Особливості механізму повернення об'єктів функціями
- •Void Set(char*s) {strcpy(str, s);}
- •Void Show() {cout «"Рядок:" « str« endl;}
- •Int mainO
- •Int mainO
- •Механізми створення та використання конструктора копії
- •Використання конструктора копії для ініціалізації одного об'єкта іншим
- •Int mainO
- •Механізм використання конструктора копії для передачі об'єкта функції
- •Int mainO
- •Механізм використання конструктора копії при поверненні функцією об'єкта
- •Int mainO
- •3.7.4. Конструктори копії та їх альтернативи
- •Поняття про ключове слово this
- •Void Fun() {...};
- •Int mainO
- •Механізми перевизначення операторів з використанням функцій-членів класу
- •Int х, у, z; //Тривимірні координати
- •Int mainO
- •Intх,у,z; //Тривимірні координати
- •Void Show(char*s);
- •Int mainO
- •Int х, у, z; //Тривимірні координати
- •Int mainO
- •Особливості реалізації механізму перевизначення операторів
- •Механізми иеревизначення операторів з використанням функцій-не членів класу
- •Використання функцій-"друзів" класу для перевизначення бінарних операторів
- •Void Show(char*s);
- •Int mainO
- •Int mainO
- •Використання функцій-"друзів" класу для перевизначення унарних операторів
- •Int mainO
- •Особливості реалізації оператора присвоєння
- •Int mainO
- •Int mainO
- •Механізми перевизначення оператора індексації елементів масиву "[]"
- •Int mainO
- •Int aMas[size]; public:
- •Int mainO
- •Int aMas[size]; public:
- •Int mainO
- •Механізми перевизначення оператора виклику функцій "()"
- •Int mainO
- •Механізми перевизначення рядкових операторів
- •Конкатенація та присвоєння класу рядків з рядками класу
- •Void Show(char*s) {cout« s « string « endl;}
- •Конкатенація та присвоєння класу рядків з рядками, що закінчуються нульовим символом
- •Void Show(char*s) {cout« s « string « endl;}
- •Void Show(char*s) {cout« s « string « endl;}
- •Int mainO
- •Поняття про успадкування в класах
- •Int kolesa; // Кількість коліс int pasagyr; // Кількість пасажирів public:
- •Int mistkist; // Вантажомісткість у м куб. Public:
- •Int kolesa; // Кількість коліс int pasagyr; // Кількість пасажирів public:
- •Int mainO
- •Використання специфікатора доступу protected для надання членам класу статусу захищеності
- •Int mainO
- •Int mainO
- •Int d; // Захищений public:
- •Int mainO
- •Protected-членом класу derived, що робить його недоступним за його межами. */
- •Void showX() {cout« х « endl;}
- •Void showY() {cout« у « endl;}
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Успадкування віртуальних функцій
- •Void Show() {cout« Суг("Другий похідний клас.") « endl;}
- •Virtual void Show() {cout« Суг("Базовий клас.") « endl;}
- •Void Show() {cout« Суг("Перший похідний клас. ")« endl;}
- •Int mainO
- •Virtual void ShowO {cout« Суг("Базовий клас.") « endl;}
- •Void Show() {cout« Суг("Перший похідний клас. ")« endl;}
- •Int mainO
- •Void Show()
- •Void Show()
- •Int mainO
- •Void Show()
- •Void Show()
- •Int mainO
- •Void swapAb(aType &а, аТуре &b)
- •Int mainO
- •Приклад створення узагальненого класу для організації безпечного масиву
- •Int mainO
- •Використання в узагальнених класах аргументів, що не є узагальненими типами
- •Використання в шаблонних класах аргументів за замовчуванням
- •Int mainO
- •Механізм реалізації безпосередньо заданої спеціалізації класів
- •Int mainO
- •Основні особливості оброблення виняткових ситуацій
- •Системні засоби оброблення винятків
- •Xtest(1);
- •Xtest(2);
- •Перехоплення винятків класового типу
- •Використання декількох catch-наетанов
- •Варіанти оброблення винятків
- •Перехоплення всіх винятків
- •Накладання обмежень на тип винятків, які генеруються функціями
- •Int mainO
- •Xhandler(o); // Спробуйте також передати функції XhandlerO аргументи 1 і 2.
- •Void Xhandler(int test) throw 0
- •Повторне генерування винятку
- •Int mainO
- •Int mainO
- •Механізми перевизначення операторів new і delete
- •Void *р;
- •Void *p;
- •Int mainO
- •Класи потоків
- •Особливості механізмів перевизначення операторів введення-виведення даних
- •Створення перевюначених операторів виведення даних
- •Int mainO
- •Використання функцій-"друзів" класу для перевюначення операторів виведення даних
- •Int х, у, z; //Тривимірні координати (тепер це private-члени) public:
- •Int mainO
- •Створення перевюначених операторів введення даних
- •Istream &operator»(istream &stream, kooClass &obj)
- •Cout«"Введіть координати X, у і z:
- •Stream » obj.X » obj.Y » obj.Z;
- •Istream &operator»(istream &stream, objectType &obj)
- •// Код операторної функції введення даних
- •Class kooClass {// Оголошення класового типу int х, у, z; // Тривимірні координати
- •Istream &operator»(istream &stream, kooClass &obj)
- •Int mainO
- •Void unsetf(fmtflags flags),
- •Void showflags(ios::fmtflags f); // Відображення поточного стану опцій
- •Int mainO
- •Ios::fmtflags f; // Оголошення параметру для поточного стану опцій
- •Int mainO
- •Створення власних маніиуляторних функцій
- •Організація файлового введення-виведення даних
- •Відкриття та закриття файлу
- •Зчитування та запис текстових файлів
- •Ifstream in(argv[1], ios::in | ios::binary); if(!in){
- •In.CloseO; getchO; return 0;
- •Int mainO
- •Зчитування та записування у файл блоків даних
- •Int mainO
- •Ifstream inftest", ios::in | ios::binary); if(!in){
- •Використання функції eof() для виявлення кінця файлу
- •If(!in.Eof()) cout« ch;
- •In.CloseO; getchO; return 0;
- •Int main(int arge, char *argv[])
- •Ifstream f1(argv[1], ios::in | ios::binary); if(!f1) {
- •Ifstream f2(argv[2], ios::in | ios::binary);
- •Int main(int arge, char *argv[])
- •Ifstream in(argv[1], ios::in | ios::binary); if(!in){
- •In.Seekg(atoi(argv[2]), ios::beg); while(in.Get(ch)) cout« ch; getchO; return 0;
- •Int х, у, z; // Тривимірні координати; вони тепер закриті public:
- •Int mainO
- •Virtual void Fun() {}; // Робимо клас Base поліморфним
- •Int mainO
- •Virtual void FunO {cout«"у класі Base"« endl;}
- •Int mainO
- •Virtual void FunO {}
- •Void derivedOnlyO {cout«"Це об'єкт класу Derived"« endl;}
- •Int mainO
- •Void Fun(const int *р)
- •Int mainO
- •Namespace ns { int d;
- •Застосування настанови using
- •Int Comp(const void *а, const void *b);
- •Int mainO
- •Int Comp(const void *a, const void *b)
- •Int mainO
- •Int Fun10 const; // const-функція-член
- •Int PutO const; return c; // Все гаразд
- •Int mainO
- •0Bj.Set(1900); cout « Obj.PutO;
- •Void setJ(int х) const // Наступна функція не відкомпілюється.
- •Int а; public:
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int myClass::*dp; // Покажчик на int-члена класу void (myClass::*fp)(int X); // Покажчик на функцію-члена
- •Int mainO
- •Механізми роботи з векторами
- •Int mainO
- •1 234 5 678 9 10 11 12 13141516 17 1819 Вміст подвоєно:
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Int mainO
- •Символи н
- •Символів представляють голосні звуки.
- •Int mainO
- •Int mainO
- •Int mainO
- •Void getaLine(string& inStr); // Отримання рядка тексту char getaCharO; //Отримання символу
- •Int aptNumber; // Номер кімнати мешканця
- •Void DisplayO; // Виведення переліку мешканців
- •Int aptNo; float rent[12]; public:
- •Void setRent(int, float); // Запис плати за місяць
- •Void insertRent(int, int, float); void DisplayO;
- •Int month, day; string category, payee; float amount; expense() {}
- •Int mainO
- •Void rentRecord::insertRent(int aptNo, int month, float amount)
- •SetPtrsRr.Insert(ptrRow); // Занести рядок вектор
- •If( setPtrsRr.Empty())
- •Else // Інакше
- •Int month, day; string category, payee; float amount;
- •«" 'Є' для запису витрат:";
- •Навчальний посібник
Код програми 2.1. Демонстрація механізму оголошення класу та його застосування
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include < math> // Для використання математичних функцій
#include <сопіо> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
class myClass { // Оголошення класового типу
double а; public:
void InitO; // Ініціалізація даних класу
void Get(double, double); // Введення в об'єкт значення double Put(); // Виведення з об'єкта значення
};
// Ініціалізація даних класу myClass. void myClass::lnit()
{
а = 0;
}
// Введення в об'єкт значення, void myClass::Get(double х, double у)
{
double а1 = pow(x,1.3); double а2 = pow(fabs(3.2*x - у),0.4); double аЗ = pow(pow(cos(a2),2),1 /3); а = а1+аЗ;
}
// Виведення з об'єкта значення, double myClass::Put()
{
return а;
int mainO
myClass ObjA, ObjB; // Створення двох об'єктів класу.
double х = 2.6, у = 7.1;
ObjA.init(); ObjB.initO;
ObjA. Get(x,у); 0bjВ. Get(x+y,y/x);
cout«"Вміст об'єкта ObjA:" « ObjA.PutO « endl;
cout«"Вміст об'єкта ObjB:" « ObjB.PutO « endl;
getchO; return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Вміст об'єкта ObjA; 4.06663
Вміст об'єкта ObjB: 20.0294
Закриті члени класу доступні тільки функціям, які є членами цього класу. Наприклад, таку настанову
ObjA.a = 0;
не можна помістити у функцію main() нашої програми.
Поняття про конструктори і деструктори
Як правило, певну частину об'єкта, перш ніж його можна буде використовувати, необхідно ініціалізувати. Наприклад, розглянемо клас myClass, який було представлено вище у цьому підрозділі. Перш ніж об'єкти класу myClass можна буде використовувати, змінній а потрібно надати нульове значення. У нашому випадку ця вимога виконувалася за допомогою функції lnit(). Але, оскільки вимога ініціалізації членів-даних класу є достатньо поширеною, то у мові програмування C++ передбачено реалізацію цієї потреби при створенні об'єктів класу. Така автоматична ініціалізація членів-даних класу здійснюється завдяки використанню конструктора.
Конструктор - це спеціальна функція-член класу, яка викликається при створенні об'єкта, а її ім'я обов'язково збігається з іменем класу. Ось, наприклад, як може виглядати клас myClass після застосування у ньому конструктора для ініціалізації членів-даних класу:
class myClass { // Оголошення класового типу
double а;
//
Оголошення конструктора // Введення в
об'єкт значення // Виведення з об'єкта
значення
myClassO;
void
Get(double, double); double Put();
};
Зверніть увагу на те, що в оголошенні конструктора myClass() відсутній тип значення, що повертається. У мові програмування C++ конструктори не повертають значень і, як наслідок, немає сенсу вказувати їх тип1.
Тепер наведемо код функції myClass():
// Визначення конструктора myClass::myClass()
{
а = 0; cout«"Об'єкт ініціалізовано" « endl;
}
У цьому випадку у процесі виконання конструктора ним виводиться повідомлення "Об'єкт ініціалізовано", яке слугує виключно ілюстративній меті. На практиці ж здебільшого конструктори не виводять ніяких повідомлень.
Конструктор об'єкта викликається при створенні об'єкта. Це означає, що він викликається у процесі виконання настанови створення об'єкта. Конструктори глобальних об'єктів викликаються на самому початку виконання програми, тобто ще до звернення до функції main(). Що стосується локальних об'єктів, то їх конструктори викликаються кожного разу, коли виникає потреба створення такого об'єкта.
Доповненням до конструктора слугує деструктор - це функція, яка викликається під час руйнування об'єкта. У багатьох випадках під час руйнування об'єкта необхідно виконати певну дію або навіть певні послідовності дій. Локальні об'єкти створюються під час входу в блок, у якому вони визначені, і руйнуються при виході з нього. Глобальні об'єкти руйнуються внаслідок завершення програми. Існує багато чинників, які заставляють використовувати деструктори. Наприклад, об'єкт повинен звільнити раніше виділену для нього пам'ять. У мові програмування C++ саме деструкторам доручається оброблення процесу деактивізації об'єкта.
Ім'я деструктора має збігатися з іменем конструктора, але йому передує символ Подібно до конструкторів, деструктори не повертають значень, а отже, в їх оголошеннях відсутній тип значення, що повертається.
Розглянемо вже знайомий нам клас myClass, але тепер він має містити конструктор і деструктор2:
class myClass { // Оголошення класового типу
double а; public:
myClass(); // Оголошення конструктора
-myCiassO; // Оголошення деструктора
void Get(double, double); // Введення в об'єкт значення double Put(); // Виведення з об'єкта значення
};
// Визначення конструктора.
myClass::myClass()
а = 0; cout«"Об'єкт ініціалізовано"« endl;
Визначення деструктора. myClass::~myClassO
cout«"Об'єкт зруйновано" « endl;
Ось як виглядатиме нова версія коду програми, призначеної для обчислення значення арифметичного виразу, у якій продемонстровано механізм використання конструктора і деструктора.
Код програми 2.2. Демонстрація механізму використання конструктора і деструктора
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include < math> // Для використання математичних функцій
#include <сопіо> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
class myClass { // Оголошення класового типу
double а; public:
myClassO; // Оголошення конструктора
~myClass(); // Оголошення деструктора
void Get(double, double); // Введення в об'єкт значення double Put(); // Виведення з об'єкта значення
};
// Визначення конструктора. myClass::myClass()
{
а = 0; cout«"Об'єкт ініціалізовано"« endl;
}
// Визначення деструктора. myClass::~myClass()
{
cout«"Об'єкт зруйновано" « endl;
}
// Введення в об'єкт значення, void myClass::Get(double х, double у)
{
double a1 = pow(x,1.3);
double a2 = pow(fabs(3.2*x - y),0.4);
double a3 = pow(pow(cos(a2),2),1./3);
а = а1+аЗ;
/ Виведення з об'єкта значення double myClass::Put()
return а;
nt mainO
myClass ObjA, ObjB; // Створення двох об'єктів класу, double х = 2.6, у = 7.1;
ObjA.Get(x,y); ObjB.Get(x+y,y/x);
cout«"Вміст об'єкта ObjA:" « ObjA.PutO « endl; cout«"Вміст об'єкта ObjB:" « ObjB.PutO « endl;
getchO; return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Об'єкт ініціалізовано Об'єкт ініціалізовано Вміст об'єкта ObjA; 4.06663 Вміст об'єкта ObjB: 20.0294 Об'єкт зруйновано.
Об'єкт зруйновано.
Параметризовані конструктори. Конструктор може мати параметри, за допомогою яких при створенні об'єкта членам-даних (змінним класу) можна надати деякі початкові значення, які визначаються у основній функції main(). Це реалізується шляхом передачі аргументів конструктору об'єкта. У наведеному нижче коді програми спробуємо удосконалити клас myClass так, щоб він приймав аргументи, які слугуватимуть ідентифікаційними номерами (п) черги. Передусім необхідно внести зміни у визначення класу myClass:
class myClass { // Оголошення класового типу
double а;
int nom; // Містить ідентифікаційний номер об'єкта
public:
myClass(int n); // Оголошення параметризованого конструктора
~myClass(); // Оголошення деструктора
void Get(double, double); // Введення в об'єкт значення double Put(); // Виведення з об'єкта значення
};
Член-даних nom використовують для зберігання ідентифікаційного номера об'єкта, який створюється основною функцією. Його реальне значення визначається значенням, яке передається конструктору як формальний параметр п при
створенні змінної типу туСІазБ. Параметризований конструктор туСІазз() буде мати такий вигляд:
// Визначення параметризованого конструктора туС Іаєз:: туС Іазз(і пі п)
{
а = 0; nom = п;
cout « "Об'єкт " « nom « " ініціалізовано" « endl;
}
Щоб передати аргумент конструктору, необхідно пов'язати цей аргумент з об'єктом під час його створення. Мова програмування С++ підтримує два способи реалізації такого зв'язування:
Варіант 1
myClass ObjA = myClass(24);
Варіант 2 (альтернативний)
myClass ObjA = 24;
#include
<vcl> #include <iostream> #include < math>
#include <conio> using namespace std;
class
myClass
{
double
а;
int
nom;
туСІазз ОЬІА(24);
Це найпоширеніший спосіб визначення параметризованих об'єктів. З використанням цього способу наведемо загальний формат передачі аргументів конструктору:
тип_кпасуім'я_об'ета{перепік_аргументів)\
У цьому записі елемент перелік_аргументів вказує на те, що усі аргументи, які передаються конструктору, розділені між собою комами.
public:
myClass(int
n); ~myClass();
void Get(double, double); // Введення в об'єкт значення
double
Put();
};
// Визначення параметризованого конструктора. myClass::myClass(int п)
{
а = 0; nom = п;
cout«"Об'єкт" « nom «" ініціалізовано" « endl;
}
// Визначення деструктора. myClass::~myClassO {
cout«"Об'єкт" « nom «" зруйновано" « endl;
}
// Введення в об'єкт значення, void myClass::Get(double х, double у)
{
double а1 = pow(x,1.3); double а2 = pow(fabs(3.2*x - у),0.4); double аЗ = pow(pow(cos(a2),2),1 /3); а = а1+аЗ;
}
// Виведення з об'єкта значення, double myClass::Put()
{
return а;
}
int mainO
{
// Створення та ініціалізація двох об'єктів. myClass ObjA(1), ObjB(2); double х = 2.6, у = 7.1;
ObjA.Get(x,y); ObjB.Get(x+y,y/x);
cout«"Вміст об'єкта ObjA:" « ObjA.PutO « endl; cout«"Вміст об'єкта ObjB:" « ObjB.PutO « endl;
getchO; return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Об'єкт 1 ініціалізовано Об'єкт 2 ініціалізовано Вміст об'єкта ObjA; 4.06663 Вміст об'єкта ObjB: 20.0294 Об'єкт 2 зруйновано Об'єкт 1 зруйновано
Як видно з коду основної функції mainO, об'єкту під іменем ObjA присвоюється ідентифікаційний номер 1, а об'єкту з іменем ObjB - ідентифікаційний номер 2.
Хоча у прикладі з використанням класу myClass при створенні об'єкта передається тільки один аргумент, у загальному випадку можлива передача двох і більше аргументів. У наведеному нижче коді програми об'єктам типу widClass передається два параметри.
Код програми 2.4. Демонстрація механізму передачі конструктору двох параметрів
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include <conio> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
class widClass { // Оголошення класового типу
int с, d; public:
widClass(int а, int b); // Оголошення параметризованого конструктора void ShowQ;
/ Передаємо 2 аргументи конструктору widClassO- widClass::widClass(int а, int b)
с = a; d = b;
cout«"Об'єкт ініціалізовано" « endl;
void widClass::Show()
cout«"c=" « c «d=" « d « endl;
nt mainO
// Створення та ініціалізація двох об'єктів. widClass ObjX(10, 20), ObjYfO, 0);
ObjX.ShowO;
ObjY.ShowO;
getchQ; return 0;
Внаслідок виконання ця програма відображає на екрані такі результати:
Об'єкт ініціалізовано
Об'єкт ініціалізовано
с=10;сі= 20
с=0;сі=0
Вартоа натиІаНа відміну від конструкторів, деструктори не мають параметрів. Причина в тому, що не існує потреби передачі значень аргументів об'єктові, який руйнується. Якщо ж у Вас виникне ситуація, коли під час виклику деструктора Вашому об'єктові необхідно отримати доступ до деяких даних, які визначаються тільки у процесі виконання програми, то для цього створіть спеціальну змінну. Потім безпосередньо перед руйнуванням об'єкта цій змінній потрібно встановити значення, яке дорівнює потрібному.