- •Міністерство надзвичайних ситуацій України Львівський державний університет безпеки життєдіяльності Юрій грицюк, Тарас рак
- •Навчальний посібник
- •Потреба використання об'єктно-орієнтованого програмування
- •Поняття про об’єктно-орієнтований підхід до розроблення складних програм
- •Основні компоненти об’єктно-орієнтованої мови програмування
- •Поняття про універсальну мову моделювання
- •Базові поняття класу
- •Код програми 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 mainO
- •Protected-членом класу derived, що робить його недоступним за його межами. */
- •Int d; // Захищений public:
- •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;
- •«" 'Є' для запису витрат:";
- •Навчальний посібник
Int х, у, z; //Тривимірні координати
public:
kooClassO {х = у = z = 0;}
kooClass(int с, int d, int f) {х = с; у = d; z = f;}
kooClass operator+(kooClass obj); // Операнд obj передається неявно. kooClass operator=(kooClass obj); // Операнд obj передається неявно, void Show(char*s);
};
// Перевизначення бінарного оператора додавання kooClass kooClass::operator+(kooClass obj)
{
kooClass tmp; // Створення тимчасового об'єкта
tmp.x = х + obj.x; // Операції додавання цілочисельних значень tmp.y = у + obj.y; // зберігають початковий вміст операндів tmp.z = z + obj.z;
return tmp; // Повертає модифікований тимчасовий об'єкт
}
// Перевизначення оператора присвоєння "=". kooClass kooClass: :operator=(kooClass obj)
{
x = obj.x; // Операції присвоєння цілочисельних значень у = obj.y; // зберігають початковий вміст операндів z = obj.z;
// Повернення модифікованого об'єкта операнда, адресованого покажчиком return *this;
// Відображення тривимірних координат х, у, z. void kooClass::Show(char*s)
{
cout«"Координати об'єкта <"« s «">:
cout«"\t\tx=" « x «", y="« у «", z=" « z « endl;
}
Int mainO
{
kooClass ObjA(1, 2, 3), ObjB(K), 10,10), ObjC;
ObjA.ShowfA");
ObjB.Show("B");
ObjC = ObjA + ObjB; // Додавання об'єктів ObjA і ObjB
ObjC.Show("C=A+B");
ObjC = ObjA + ObjB + ObjC; // Множинне додавання об'єктів ObjC.Show("C=A+B+C");
ObjC = ObjB = ObjA; // Множинне присвоєння об'єктів
ObjB.Show("B=A");
ObjC.Show("C=B"); getchO; return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Координати об'єкта <А>: х= 1, у= 2, z= З
Координати об'єкта <В>: х= 10, у= 10, z= 10
Координати об'єкта <С=А+В>: х= 11, у= 12, z= 13
Координати об'єкта <С=А+В+С>: х= 22, у= 24, z= 26
Координати об'єкта <В=А>: х= 1, у= 2, z= З
Координати об'єкта <С=В>: х= 1, у= 2, z= З
Аналізуючи код цієї програми, можна побачити, що обидві операторні функції мають тільки по одному параметру, хоча вони перевизначають бінарні операції. Цю, на перший погляд, "кричущу" суперечність можна легко пояснити. Йдеться про те, що при перевизначенні бінарного оператора з використанням функції- члена класу їй передається безпосередньо тільки один аргумент. Другий же опосередковано передається через покажчик this. Таким чином, у рядку tmp.x = х + obj.x;
під членом-даних х маємо на увазі член this->x, тобто член х зв'язується з об'єктом, який викликає дану операторну функцію. В усіх випадках опосередковано передається об'єкт, який вказується зліва від символу операції, тобто той, який став причиною виклику операторної функції. Об'єкт, який розташовується з правого боку від символу операції, передається цій функції як аргумент. У загальному випадку під час застосування функції-члена класу для перевизначення унарного оператора параметри не використовуються взагалі, а для перевизначення бінарного оператора береться до уваги тільки один параметр1. У будь-якому випадку об'єкт, який викликає операторну функцію, опосередковано передається через покажчик this.
Нео! хідноапам'ятати! Якщо для перевизиачеиия бінарного оператора використовується функція-член класу, то об'єкт, який знаходиться зліва від операції, викликає операторну функцію і передається їй опосередковано через покажчик this. Об'єкт, який розташовується праворуч від операції, передається операторній функції як параметр.
Щоб зрозуміти механізм перевизначення операторів, розглянемо уважно наведену вище програму, починаючи з перевизначеного оператора додавання Під час оброблення двох об'єктів типу kooClass оператором додавання "+" виконуються операції додавання значень відповідних координат так, як це показано у функції operator+(). Але зауважте, що ця операторна функція не модифікує значень жодного операнда. Як результат виконання операції ця функція повертає об'єкт типу kooClass, який містить результати попарного додавання координат двох об'єктів. Щоб зрозуміти, чому операція "+" не змінює вміст жодного з об'єктів-учасників, розглянемо стандартну арифметичну операцію додавання, що застосовується, наприклад, до чисел 10 і 12. Отож, результат виконання операції 10+12 дорівнює 22, але при його отриманні ні число 10, ні 12 не були змінені. Хоча не існує правила, яке б не давало змоги перевизначеному оператору змінювати значення одного з його операндів, все ж таки краще, щоб він не суперечив загальноприйнятим нормам і залишався у згоді зі своїм оригінальним призначенням.
Зверніть увагу на те, що операторна функція operator+О повертає об'єкт типу kooClass, хоча вона могла б повертати значення будь-якого іншого допустимого типу, що визначається мовою програмування C++. Однак, той факт, що вона повертає об'єкт типу kooClass, дає змогу використовувати оператор додавання "+" у таких складних виразах, як ObjA + ObjB + ObjC - множинне додавання. Частина цього виразу (ObjA + ObjB) отримує результат типу kooClass, який потім додається до об'єкта ObjC. І якби ця частина виразу генерувала значення іншого типу (а не типу kooClass), то таке множинне додавання просто не відбулося б.
На відміну від оператора додавання "+", оператор присвоєння "=" модифікує один зі своїх аргументів1. Оскільки операторна функція operator=0 викликається об'єктом, який розташований зліва від символу присвоєння "=", то саме цей об'єкт і модифікується внаслідок виконання операції присвоєння. Після виконання цієї операції значення, яке повертається перевизначеним оператором, містить об'єкт, який було вказано зліва від символу присвоєння2. Наприклад, щоб можна виконувати настанови, подібні до такої (множинне присвоєння)
ObjA = ObjB = ObjC = ObjD;, необхідно, щоб операторна функція operator=0 повертала об'єкт, який адресується покажчиком this, і щоб цей об'єкт розташовувався зліва від оператора присвоєння "=". Це дасть змогу виконати будь-який ланцюжок присвоєнь.
Операція присвоєння - це одне з найважливіших застосувань покажчика this.
Перевюначення унарних операторів інкремента "++" та декремента
Можна перевнзначатн унарні оператори інкремента "++" та декремента або унарні і Як уже зазначалося вище, при перевизначенні унарного оператора за допомогою функції-члена класу операторній функції жоден об'єкт не передається безпосередньо. Операція ж здійснюється над об'єктом, який викликає цю функцію через опосередковано переданий покажчик this. Наприклад, розглянемо дещо змінену версію попереднього коду програми. У наведеному нижче його варіанті для об'єктів типу kooClass визначається бінарна операція віднімання та унарна операція інкремента .
Код програми 4.2. Демонстрація механізму перевизначення префіксної форми унарного оператора інкремента "++"
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include <conio> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
class kooClass { // Оголошення класового типу
