
- •Міністерство надзвичайних ситуацій України Львівський державний університет безпеки життєдіяльності Юрій грицюк, Тарас рак
- •Навчальний посібник
- •Потреба використання об'єктно-орієнтованого програмування
- •Поняття про об’єктно-орієнтований підхід до розроблення складних програм
- •Основні компоненти об’єктно-орієнтованої мови програмування
- •Поняття про універсальну мову моделювання
- •Базові поняття класу
- •Код програми 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;
- •«" 'Є' для запису витрат:";
- •Навчальний посібник
Virtual void ShowO {cout« Суг("Базовий клас.") « endl;}
};
// Клас firstD виведений з класу baseClass
class firstD : public baseClass { public:
Void Show() {cout« Суг("Перший похідний клас. ")« endl;}
};
// Клас secondD тепер виведений з класу firstD, а не з класу baseClass. class secondD : public firstD {
// Функція ShowO не визначена.
};
Int mainO
{
baseClass ObjB; // Створення об'єкта базового типу baseClass *bp; // Створення покажчика на об'єкт базового типу firstD ObjF; // Створення об'єкта похідного типу
secondD ObjS; // Створення об'єкта похідного типу
bp = &ObjB; // Присвоєння покажчику адреси об'єкта базового класу
bp->Show(); // Доступ до функції ShowO baseClass
bp = &ObjF; // Присвоєння покажчику адреси об'єкта похідного класу
bp->ShowO; // Доступ до функції ShowO кл^У firs®
bp = &ObjS; // Присвоєння покажчику адреси об'єкта похідного класу
bp->ShowO; І* Тут здійснюється звернення до функції ShowO
класу firstD, оскільки у класі secondD її не перевизначено. */
getchO; return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати: Базовий клас.
Перший похідний клас.
Перший похідний клас.
Як бачите, похідний клас secondD тепер використовує версію функції ЄІ^О, яку визначено у похідному класі АгаЮ, оскільки вона знаходиться найближче в ієрархічному ланцюжку класів.
Потреба у застосуванні віртуальних функцій
Як наголошувалося на початку цього розділу, віртуальні функції у поєднанні
з похідними типами дають змогу мові програмування С++ підтримувати динамічний поліморфізм. Він для об'єктно-орієнтованого програмування є важливим з однієї причини: дає змогу деякому узагальненому класу визначати функції, які використовуватимуть усі похідні від нього класи, причому похідний клас може визначити власну реалізацію усіх або деяких цих функцій. Іноді ця ідея виражається так: базовий клас диктує загальний інтерфейс, який матиме будь-який об'єкт, виведений з цього класу, але при цьому дає змогу похідному класу визначити метод, який використовують для реалізації цього інтерфейсу. Ось чому для опису поліморфізму часто використовують фраза - один інтерфейс, багато методів.
Для успішного застосування поліморфізму необхідно розуміти, що базовий і похідний класи утворюють ієрархію, розвиток якої спрямований від більшого до меншого ступеня узагальнення (тобто від базового класу до похідного). У разі коректної реалізації базовий клас забезпечує всі елементи, які похідний клас може використовувати безпосередньо. Він також визначає функції, які похідний клас повинен реалізувати самостійно. Це дає похідному класу гнучкість у визначенні власних методів, але водночас зобов'язує використовувати загальний інтерфейс. Іншими словами, оскільки формат інтерфейсу визначається базовим класом, то будь-який похідний клас повинен розділяти цей загальний інтерфейс. Таким чином, застосування віртуальних функцій дає змогу базовому класу визначати узагальнений інтерфейс, який використовуватиметься всіма похідними класами.
Тепер у Вас може виникнути запитання: чому ж такий важливий загальний інтерфейс з множиною реалізацій? Відповідь знову повертає нас до основної спонукальної причини виникнення об'єктно-орієнтованого програмування: такий інтерфейс дає змогу програмісту справлятися із наростаючою складністю програм. Наприклад, якщо коректно розробити програму, то можна упевнитися в тому, що до всіх об'єктів, виведених з базового класу, можна буде отримати доступ єдиним (загальним для всіх) способом, незважаючи на те, що конкретні дії одного похідного класу можуть відрізнятися від дій іншого. Це означає, що програмісту доведеться пам'ятати тільки один інтерфейс, а не велику їх кількість. Окрім цього, похідний клас має можливість використовувати будь-які або всі функції, надані базовим класом. Іншими словами, розробнику похідного класу не потрібно наново винаходити елементи, які вже є в базовому класі. Понад це, від'єднання інтерфейсу від реалізації дає змогу створювати бібліотеки класів, написанням яких можуть займатися сторонні організації. Коректно реалізовані бібліотеки повинні надавати загальний інтерфейс, який програміст може використовувати для виведення похідних класів відповідно до своїх конкретних потреб. Наприклад, як бібліотека базових класів Microsoft (Microsoft Foundation Classes - MFC), так і новіша бібліотека класів .NET Framework Windows Forms підтримують Windows-nporpa- мування. Використання цих класів дає змогу розробляти програми, які можуть успадкувати багато функцій, потрібних будь-якій Windows-програмі. Вам знадобиться тільки додати в неї засоби, унікальні для Вашої програми. Це - велика допомога при програмуванні складних ієрархічних систем.
Приклад застосування віртуальних функцій
Щоб Ви могли отримати уявлення про потужність механізму "один інтерфейс, багато методів", розглянемо таку навчальну програму. Вона створює базовий клас figure, призначений для зберігання розмірів різних двовимірних об'єктів і обчислення їх площ. Функція SetO є стандартною функцією-членом класу, оскільки вона підходить для всіх похідних класів. Проте функція ShowO оголошена як віртуальна, оскільки методики обчислення площі різних об'єктів будуть різними. Програма використовує базовий клас figure для виведення двох спеціальних класів rectangle і triangle.
Код програми 6.5. Демонстрація механізму застосування віртуальних функцій #include <vcl>
#include <conio>
#include <iostream> // Для потокового введення-виведення using namespace std; // Використання стандартного простору імен
class figure { protected:
double x, у; public:
void Set(double _x, double _y) {x = _x; у = _y;} virtual void Show()
{
cout« Суг("У цьому класі виразу для обчислення площі не визначено.") « endl;
}
};
class triangle: public figure { public: