
- •Міністерство надзвичайних ситуацій України Львівський державний університет безпеки життєдіяльності Юрій грицюк, Тарас рак
- •Навчальний посібник
- •Потреба використання об'єктно-орієнтованого програмування
- •Поняття про об’єктно-орієнтований підхід до розроблення складних програм
- •Основні компоненти об’єктно-орієнтованої мови програмування
- •Поняття про універсальну мову моделювання
- •Базові поняття класу
- •Код програми 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;
- •«" 'Є' для запису витрат:";
- •Навчальний посібник
Int main(int arge, char *argv[])
{
char ch; if(argc !=3) {
cout«"Застосування: ім'я_програми"«"<ім'я_файлу> <стартова_позиція>"« endl; return 1;
}
Ifstream in(argv[1], ios::in | ios::binary); if(!in){
cout«"He вдається відкрити файл" « endl; return 1;
}
In.Seekg(atoi(argv[2]), ios::beg); while(in.Get(ch)) cout« ch; getchO; return 0;
}
Використання перевизначених операторів введення-виведен- ня даних при роботі з файлами
Вище Ви вже дізналися, як перевизначати оператори введення-виведення для власних класів, а також як створювати власні маніпулятори. У наведених вище прикладах програм виконувалися тільки операції консольного введення-виведен- ня. Але, оскільки всі С++-потоки однакові, то одну і ту саму операторну функцію виведення даних, наприклад, можна використовувати для виведення інформації як на екран, так і у файл, не вносячи при цьому ніяких істотних змін. Саме у цьому і полягають основні переваги С++-системи введення-виведення.
У наведеному нижче коді програми використано перевизначений (для класу kooClass) оператор виведення даних для записування значень поточних координат у файл threed.
Код програми 9.21. Демонстрація механізму використання перевизначеного оператора введення-виведення даних для запису об'єктів класу у файл
#include <iostream> // Для потокового введення-виведення
#include <fstream> // Для роботи з файлами
using namespace std; // Використання стандартного простору імен class kooClass {// Оголошення класового типу
Int х, у, z; // Тривимірні координати; вони тепер закриті public:
kooClass(int а, int b, int с) {х = а; у = b; z = с;}
friend ostream &operator«(ostream &stream, kooClass obj);
};
// Відображення тривимірних координат х, у, z // Перевизначений оператор виведення даних для класу kooClass ostream &operator«(ostream &stream, kooClass obj)
{
stream « obj.x «", stream « obj.y «", stream « obj.z « endl;
return stream; // Повертає посилання на параметр stream
}
Int mainO
{
kooClass ObjA(1, 2,3), ObjB(3,4, 5), ObjC(5, 6, 7); ofstream outfthreed");
if(!out) {
cout«"Не вдається відкрити файл."; return 1;
}
// Перевизначений оператор виведення даних out « ObjA « ObjB « ObjC;
out.closeO;
getchO; return 0;
}
Якщо порівняти цю версію операторної функції виведення даних для класу kooClass з тією, що була представлена на початку цього розділу, то можна переконатися у тому, що для "налаштування" її на роботу з дисковими файлами ніяких змін вносити не довелося. Якщо оператори введення-виведення визначені коректно, то вони успішно працюватимуть з будь-яким потоком.
Вартоа' нати'.аПерш ніж переходити до наступного розділу, не пошкодуйте часу і попрацюйте з С++-функціями введення-виведення. Створіть власний клас, а потім визначте для нього оператори введення-виведення. А ще створіть власні маніпулятори.
Розділ 10. ДИНАМІЧНА ІДЕНТИФІКАЦІЯ ТИПІВ 1 ОПЕРАТОРИ ПРИВЕДЕННЯ ТИПУ
У цьому розділі розглянемо два засоби мови програмування C++, які підтримують сучасне ООП: динамічна ідентифікація типів (run-time type identification - RTTI) і набір додаткових операторів приведення типу. Жоден з цих засобів не був частиною оригінальної специфікації мови програмування C++, але обидва вони були додані у нову версію мови C++ з метою посилення підтримки поліморфізму тривалості виконання. Під RTTI розуміють можливість проведення ідентифікації типу об'єкта у процесі виконання програми. Оператори приведення типу, що розглядаються у цьому розділі, пропонують програмісту безпечніші способи виконання цієї операції. Як буде показано далі, один з них - dynamic_cast безпосередньо пов'язаний з RTTI-ідентифікацією, тому оператори приведення типу і RTTI є сенс розглядати в одному розділі.
Динамічна ідентифікація типів
З динамічною ідентифікацією типів (RTTI) більшість традиційних програмістів незнайомі, оскільки цей засіб відсутній у такій неполіморфній мові, як С. У не- поліморфних мовах просто немає потреби в отриманні інформації про тип у процесі виконання програми, оскільки тип кожного об'єкта відомий при компілюванні (тобто ще під час написання програми). Але в такій поліморфній мові, як C++, можливі ситуації, в яких тип об'єкта невідомий у період компілювання, оскільки точна природа цього об'єкта не буде визначена доти, доки програма на почне виконуватися. Як уже зазначалося вище, мова програмування C++ реалізує поліморфізм за допомогою використання ієрархії класів, віртуальних функцій і покажчиків на об'єкти базових класів. Покажчик на базовий клас можна використовувати для посилання на члени як цього базового класу, так і на члени будь-якого об'єкта, виведеного з нього. Отже, не завжди наперед відомо, на об'єкт якого типу посилатиметься покажчик на базовий клас у довільний момент часу. Це з'ясується тільки у процесі виконання програми - при використанні одного із засобів динамічної ідентифікації типів.
Отримання типу об'єкта у процесі виконання програми
Для цього необхідно приєднати до програми заголовок <typeinfo>. Найпоширеніший формат використання оператора typeid такий:
typeid(ob/ec/)
У цьому записі елемент object означає об'єкт, тип якого потрібно отримати. Можна робити запити не тільки про вбудований тип, але і про тип класу, створеного програмістом. Оператор typeid повертає посилання на об'єкт типу type_info, який описує тип об'єкта object.
У класі type_info визначено такі public-члени: bool operator==(const type_info &ob);
bool operator!=(const type_info &ob);
bool before(const type_info &ob);
const char*name();
Перевизначені оператори "==" і "!=" слугують для порівняння типів. Функція beforeO повертає значення true, якщо викликаючий об'єкт у порядку зіставлення знаходиться перед об'єктом (елементом ob), що використовується як параметр1. Функція nameO повертає покажчик на ім'я типу.
Розглянемо простий приклад використання оператора typeid.
Код програми 10.1. Демонстрація механізму використання оператора typeid #include <iostream> // Для потокового введення-виведення
#include <typeinfo> // Для динамічної ідентифікації типів
using namespace std; // Використання стандартного простору імен
class myClass {// Оголошення класового типу //...
};
int mainO
{
int с, d; float f;
myClass obj;
cout«"Тип змінної c:" «typeid(c).nameO « endl;
cout«"Тип змінної f:" «typeid(f).nameO « endl;
cout«"Тип змінної obj:" «typeid(obj).nameO « endl « endl;
if(typeid(c) == typeid(d))
cout«"Типи змінних c та d однакові" « endl;
if(typeid(c) != typeid(f))
cout«"Типи змінних c та f неоднакові" « endl; getchO; return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Тип змінної с: int
Тип змінної f: float
Тип змінної obj: dass myClass
Типи змінних с та d однакові.
Типи змінних с та f неоднакові.
Якщо оператор typeid застосовується до покажчика на поліморфний базовий клас (пригадайте: поліморфний клас - це клас, який містить хоч би одну віртуальну функцію), він автоматично повертає тип реального об'єкта, на який той вказує: будь то об'єкт базового класу або об'єкт класу, виведеного з базового.
Отже, оператор typeid можна використовувати для динамічного визначення типу об'єкта, який адресується покажчиком на базовий клас. Застосування цієї можливості продемонстровано в такому коді програми.
Код програми 10.2. Демонстрація механізму застосування оператора typeid до ієрархії поліморфних класів #include <iostream> // Для потокового введення-виведення
#include <typeinfo> // Для динамічної ідентифікації типів
using namespace std; // Використання стандартного простору імен
// Оголошення базового класу class Base {