Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Не підтверджено.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
3.08 Mб
Скачать

Void *р;

cout«"Виділення області пам'яті для об'єкта класу kooClass" « endl; р = malloc(size);

// Генерування винятку у разі невдалого виділення області пам'яті. if№){

bad_alloc ba; throw ba;

}

return p;

}

// Перевизначення оператора new для масиву об'єктів типу kooClass. void *kooClass::operator new[](size_t size)

{

Void *p;

cout«"Виділення області пам'яті для масиву kooClass-об'єктів" « endl; //Генерування винятку при невдачі, р = malloc(size); if№){

bad_alloc ba; throw ba;

}

return p;

}

// Перевизначення оператора delete для класу kooClass. void kooClass: operator delete(void *p)

{

cout«"Видалення об'єкта класу kooClass"« endl; free(p);

}

// Перевизначення оператора delete для масиву об'єктів типу kooClass. void kooClass: operator delete[](void *p)

{

cout«"Видалення масиву об'єктів типу kooClass" « endl; free(p);

}

// Відображення тривимірних координат х, у, z. void kooClass: :showB(char*s)

{

cout«"Координати об'єкта <"« s «">:";

cout«"\t\tx=" « x «", y="« у «", z=" « z « endl;

}

Int mainO

{

kooClass *p1,*p2; try {

p1 = new kooClass[3]; // Виділення області пам'яті для масиву р2 = new kooClass(5,6,7); // Виділення області пам'яті для об'єкта

}

catch(bad_alloc ba) {

cout«"Помилка під час виділення області пам'яті"« endl; return 1;

}

p1[1].showB("Ba30BHÜ клас:"); p2->showB("Ba30BHÜ клас:");

delete []р1; //Видалення масиву delete р2; // Видалення об'єкта getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати: Виділення області пам'яті для масиву kooClass-об'єктів.

Створення об'єкта 0,0,0 Створення об'єкта 0,0,0 Створення об'єкта 0,0,0

Виділення області пам'яті для об'єкта класу kooClass.

Створення об'єкта 5,6,7

0,0,0

5,6,7

Руйнування об'єкта Руйнування об'єкта Руйнування об'єкта

Видалення масиву об'єктів типу kooClass.

Руйнування об'єкта Видалення об'єкта класу kooClass.

Перші три повідомлення Створення об'єкта 0,0,0 видані конструктором класу ko­oClass (який не має параметрів) під час виділення області пам'яті для триелемен- тного масиву. Як уже зазначалося вище, під час виділення області пам'яті для ма­сиву автоматично викликається конструктор кожного елемента. Повідомлення Створення об'єкта 5, 6, 7 видано конструктором класу kooClass (який приймає три аргу­менти) під час виділення області пам'яті для одного об'єкта. Перші три повідом­лення Руйнування об'єкта видані деструктором внаслідок видалення триелементного масиву, оскільки при цьому автоматично викликався деструктор кожного елемен­та масиву. Останнє повідомлення Руйнування об'єкта видане під час видалення одно­го об'єкта класу kooClass. Важливо розуміти, що, коли оператори new і delete пере- визначені для конкретного класу, то внаслідок їх використання для даних інших типів будуть задіяні оригінальні версії операторів new і delete. Це означає, що при додаванні у функцію mainO наступного рядка буде виконано стандартну версію оператора new:

int *f = new int; // Використовується стандартна версія оператора new.

Вартоа нати! Оператори new і delete можна перевизначати глобально. Для цього достатньо оголосити їх операторні функції поза класами. У цьому ви­падку стандартні версії C++-операторів new і delete ігноруються взагалі, і в усіх запитах на виділення області пам'яті використовуються їх перевизначе- ні версії. Безумовно, якщо Ви при цьому визначите версію операторів new і de­lete для конкретного класу, то ці "класові" версії застосовуватимуться під час виділення області пам'яті (та її звільнення) для об'єктів цього класу. В усій же решті випадків використовуватимуться глобальні операторні функції.

Перевизначення nothrow-версїі оператора new. Можна також створити пе- ревизначені nothrow-версії операторів new і delete. Для цього використовуються та­кі механізми:

// Перевизначення nothrow-версії оператора new void ‘operator new(size_t size, const nothrow_t &n)

{

// Виділення області пам'яті. if(success) return pointer_to_memory; else return 0;

}

// Перевизначення nothrow-версії оператора new для масиву, void ‘operator new[](size_t size, const nothrow_t &n)

{

// Виділення області пам'яті. if(success) return pointer_to_memory; else return 0;

}

// Перевизначення nothrow-версії оператора delete, void operator delete(void *p, const nothrow_t &n)

{

// Звільнення пам'яті.

}

// Перевизначення nothrow-версії оператора delete для масиву, void operator delete[](void *p, const nothrow_t &n)

{

// Звільнення пам'яті.

}

Тип nothrow_t визначається в заголовку <new>. Параметр типу nothrow_t не ви­користовується. Як вправу проекспериментуйте з throw-версіями операторів new і delete самостійно.

Розділ 9. ОРГАНІЗАЦІЯ С++-СИСТЕМИ ВВЕДЕННЯ-ВИВЕДЕННЯ ПОТОКОВОЇ ІНФОРМАЦІЇ

З самого початку висвітлення матеріалу у цьому навчальному посібнику ви­користовувалася С++-система введення-виведення потокової інформації, але не наводилось детальних пояснень з механізму її реалізації. Оскільки С++-система введення-виведення побудована на ієрархії класів, то її теорію і деталі реалізації неможливо було засвоїти, не розглянувши спочатку механізм реалізації класів, ус­падкування в класах і оброблення винятків. Якраз після цього і настає момент для детального вивчення С++-засобів введення-виведення потокової інформації.

У цьому розділі будуть розглядатися засоби як консольного, так і файлового введення-виведення потокової інформації. Необхідно зразу ж відзначити, що С++- система введення-виведення - достатньо широка тема. Тому у поданому нижче матеріалі описано тільки найважливіші та часто вживані засоби організації С++- системи введення-виведення. Зокрема, спочатку дізнаємося про те, що розуміють під потоками у мові програмування С++, про перевизначення операторів "«" і ">>" для введення та виведення об'єктів, про форматування різних типів даних, а також про використання маніпуляторів введення-виведення. На завершення розді­лу переглянемо засоби файлового введення-виведення потокової інформації.

  1. Порівняння С- та С++-систем введення-виведення

На сьогодні існують дві версії бібліотеки об'єктно-орієнтованого введення- виведення даних, причому обидві широко використовуються програмістами: ста­ра [дод. А, 9], що базується на оригінальних специфікаціях мови С, і нова - визна­чається стандартом мови програмування С++. Стара бібліотека введення-виведен- ня даних підтримується за рахунок заголовного файлу <іоз(геат.И>, а нова - за до­помогою заголовка <іоз(геат>. Нова бібліотека введення-виведення даних загалом є оновленою і вдосконаленою версією старої. Основна відмінність між ними по­лягає в механізмі реалізації засобів введення-виведення потокової інформації, а не у тому, як їх потрібно використовувати.

З погляду програміста, є дві істотні відмінності між старою С- і новою С++- бібліотеками введення-виведення. По-перше, нова бібліотека містить ряд додатко­вих засобів і визначає декілька нових типів даних. Тому нову бібліотеку С++-сис- теми введення-виведення можна вважати надбудовою над старою С-системою. Практично всі програми, що були написані раніше з використанням старої біблі­отеки, успішно компілюються тепер за наявності нової бібліотеки, не вимагаючи внесення будь-яких значних змін у самій програмі. По-друге, стара бібліотека С- системи введення-виведення була визначена в глобальному просторі імен, а нова використовує простір імен біс) (пригадайте, що простір імен вісі використовується всіма бібліотеками стандарту мови програмування С++). Оскільки С-бібліотека введення-виведення даних вже дещо застаріла, то у цьому навчальному посібнику описується тільки нова її версія. Водночас велика частина наведеного нижче мате­ріалу повного мірою стосується і старої бібліотеки.

  1. Поняття "потоків" у мові програмування C++

Принциповим для розуміння С++-СИСТЄМИ введення-виведення є те, що вона базується на понятті "потоку". Потік (stream) - це загальний логічний інтерфейс з різними пристроями, з яких складається комп'ютер. Потік або синтезує інформа­цію, або споживає її, після чого зв'язується з будь-яким фізичним пристроєм за допомогою С++-СИСТЄМИ введення-виведення. Характер поведінки всіх потоків є однаковим, незважаючи на різні фізичні пристрої, з якими вони пов'язуються. Ос­кільки різні потоки діють однаково, то практично до всіх типів пристроїв можна застосувати одні і ті ж самі функції та оператори введення-виведення. Наприклад, методи, що використовуються для виведення даних на екран, також можна вико­ристовувати для виведення їх на друкувальний пристрій або для запису у диско­вий файл.

  1. Файлові C++-потоки

У загальному випадку потік можна назвати логічним інтерфейсом з файлом. У мові програмування C++ до терміну "файл" належать дискові файли, екран мо­нітора, клавіатура, порти, файли на магнітній стрічці й ін. Хоча файли між собою відрізняються за формою і можливостями представлення, проте робота з різними потоками інформації є однаковою. Перевага цього підходу (з погляду програміс­та) полягає у тому, що один пристрій комп'ютера може бути подібним до будь- якого іншого. Це означає, що потік забезпечує інтерфейс, який узгоджується зі всіма пристроями.

Потік зв язується з файлом у процесі виконання операції відкриття файлу, а відокремлюється від нього за допомогою операції його закрит­тя.

Існує два типи потоків: текстовий і двійковий. Текстовий потік використову­ють для введення-виведення символів. При цьому можуть відбуватися деякі пе­ретворення символів. Наприклад, під час виведення символ нового рядка може пе­ретворюватися у послідовність символів: повернення каретки і переходу на новий рядок. Тому часто не буває взаємно-однозначної відповідності між тим, що поси­лається у потік, і тим, що насправді записується у файл. Двійковий потік можна використовувати з даними будь-якого типу, причому у цьому випадку ніякого пе­ретворення символів не здійснюється, тобто між тим, що посилається у потік, і тим, що потім реально міститься у файлі, існує взаємно-однозначна відповідність.

Розглядаючи потоки, необхідно розуміти, що вкладається у поняття "поточ­ної позиції". Наприклад, якщо довжина файлу дорівнює 100 байтів, і відомо, що вже прочитано його половину, то наступна операція зчитування почнеться на 50- му байті, який у цьому випадку і є поточною позицією.

Поточнаапо' иція — це те місце у файлі, з якого буде виконуватися наступна операція доступу до його даних.

Отже, у мові програмування C++ механізм введення-виведення потокової ін­формації функціонує з використанням логічного інтерфейсу, який називається по­током. Всі потоки мають аналогічні властивості, які дають змогу використовува­ти однакові функції введення-виведення, незалежно від того, з файлом якого типу існує зв'язок. Під файлом розуміють реальний фізичний пристрій, який містить дані. Якщо файли можуть відрізнятися між собою, то потоки - ні. Водночас, якщо деякі пристрої можуть не підтримувати всі операції введення-виведення даних (наприклад, операції з довільною вибіркою), то і пов'язані з ними потоки теж не підтримуватимуть ці операції.

  1. Вбудовані С++-потоки

У мові програмування C++ міститься ряд вбудованих однобайтових (8-біто- вих) потоків (сіп, cout, cerr і clog), які автоматично відкриваються, як тільки прог­рама починає виконуватися. Як уже зазначалося вище, сіп - це стандартний вхід­ний, a cout - стандартний вихідний потік. Потоки cerr і clog (вони призначені для виведення інформації про помилки) також пов'язані із стандартним виведенням даних. Різниця між ними полягає у тому, що потік clog є буферизованим, а потік cerr - ні. Це означає, що будь-які вихідні дані, послані у потік cerr, будуть негайно виведені на екран, а при використанні потоку clog дані спочатку записуються в бу­фер, а реальне їх виведення починається тільки тоді, коли буфер повністю запов­нено. Зазвичай потоки cerr і clog використовують для виведення інформації на ек­ран про стан відлагодження програми або її помилки.

У мові програмування C++ також передбачено двобайтові (16-бітові) сим­вольні версії стандартних потоків, що іменуються wein, wcout, weerr і wclog. Вони призначені для підтримки таких мов як китайська, японська та інших східно- азійських, для представлення яких потрібні великі символьні набори. У цьому на­вчальному посібнику двобайтові стандартні потоки не розглядаються.

За замовчуванням стандартні С++-потоки зв'язуються з монітором, але прог­рамним способом їх можна перенаправити на інші зовнішні пристрої або дискові файли. Перенаправлення може також виконати сама операційна система.