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

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;

}

  1. Використання перевизначених операторів введення-виведен- ня даних при роботі з файлами

Вище Ви вже дізналися, як перевизначати оператори введення-виведення для власних класів, а також як створювати власні маніпулятори. У наведених вище прикладах програм виконувалися тільки операції консольного введення-виведен- ня. Але, оскільки всі С++-потоки однакові, то одну і ту саму операторну функцію виведення даних, наприклад, можна використовувати для виведення інформації як на екран, так і у файл, не вносячи при цьому ніяких істотних змін. Саме у цьо­му і полягають основні переваги С++-системи введення-виведення.

У наведеному нижче коді програми використано перевизначений (для класу 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 є сенс розглядати в одному розділі.

  1. Динамічна ідентифікація типів

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

  1. Отримання типу об'єкта у процесі виконання програми

Для цього необхідно приєднати до програми заголовок <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 {