67370

Перевантаження операторів введення-виведення даних

Лекция

Информатика, кибернетика и программирование

У розглянутих раніше прикладах програм для виконання операції введення або виведення «класових» даних створювалися функції-члени класів, призначення яких полягало тільки у тому, щоб ввести або вивести ці дані. Незважаючи на те, що у такому вирішенні цих питань немає нічого неправильного, проте у мові...

Украинкский

2014-09-07

85.5 KB

11 чел.

Лекція № 27

Тема: Перевантаження операторів введення-виведення даних

План

  1.  Особливості механізмів перевантаження операторів введення-виведення даних
  2.  Створення перевантажених операторів виведення даних
  3.  Використання функцій-"друзів" класу для перевантаження операторів виведення даних
  4.  Створення перевантажених операторів введення даних
  5.  Порівняння С- і С++-систем введення-виведення

  1.  Особливості механізмів перевантаження операторів введення-виведення даних

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

    У мові C++ оператор "<<" називається оператором виведення або вставлення, оскільки він вставляє символи у потік. Аналогічно оператор ">>" називається оператором введення або вилучення, оскільки він вилучає символи з потоку.

    Як уже зазначалося вище, оператори введення-виведення вже перевантажені (у заголовку <iostream>) для того, щоби вони могли виконувати операції потокового введення або виведення даних будь-яких вбудованих С++-типів. У цьому підрозділі можна буде дізнатися про те, як визначити ці оператори для створення власних класів.

  1.  Створення перевантажених операторів виведення даних

    Як простий приклад розглянемо механізм створення оператора виведення даних для уже відомої нам з попередніх тем такої версії класу kooClass:

class kooClass

{    public:

             int x, y, z;                         // Тривимірні координати

             kooClass(int a, int b, int c) { x = a; y = b; z = c; }

};

    Щоб створити операторну функцію виведення даних для об'єктів типу kooClass, необхідно перевантажити оператор виведення даних "<<". Один з можливих способів його реалізації має такий вигляд:

       

        // Відображення тривимірних координат x, y, z

        // Перевантажений оператор виведення даних для класу kooClass

ostream &operator<<(ostream &stream, kooClass obj)

{

stream << obj.x << ", ";

stream << obj.y << ", ";

stream << obj.z << endl;

return stream;    // Повертає посилання на параметр stream

}

  Розглянемо уважно цю операторну функцію, оскільки її вміст характерний для багатьох операторних функцій виведення даних. По-перше, зверніть увагу на те, що, згідно з оголошенням, вона повертає посилання на об'єкт типу ostream. Це дає змогу декілька звичайних операторів виведення даних об'єднати в одному складеному виразі. По-друге, зверніть увагу також на те, що ця функція має два параметри. Перший є посиланням на потік, який використовується в лівій частині оператора "<<". Другим є об'єкт, який знаходиться у правій частині цього оператора. Саме тіло операторної функції складається з настанов виведення трьох значень координат, що містяться в об'єкті типу kooClass, і настанови повернення потоку stream. Нижче наведено навчальну програму, у якій продемонстровано механізм використання перевантаженого оператора виведення даних.

Приклад. Демонстрація механізму реалізації перевантаженого оператора виведення даних

class kooClass

{

    public:

            int x, y, z;

            kooClass(int a, int b, int c) { x = a; y = b; z = c; }

};

    // Відображення тривимірних координат x, y, z

    // Перевизначений оператор виведення даних для класу kooClass

ostream &operator<<(ostream &stream, kooClass obj)

{

stream << obj.x << ", ";

stream << obj.y << ", ";

stream << obj.z << endl;

return stream; // Повертає посилання на параметр stream

}

void main()

{

kooClass ObjA(1, 2, 3), ObjB(3, 4, 5), ObjC(5, 6, 7);

      // Перевизначений оператор виведення даних

cout << ObjA << ObjB << ObjC;

}

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

1, 2, 3

3, 4, 5

5, 6, 7

   Якщо видалити програмний код, який стосується звичайних операторів виведення даних конкретного класу kooClass, то залишиться "скелет", що відповідає будь-якій операторній функції виведення даних:

ostream &operator<<(ostream &stream, class_type obj)

{

// Код операторної функції виведення даних

return stream; // Повертає посилання на параметр stream

}

   Як було уже наголошено вище, для параметра obj дозволяється використовувати посилання для його передачі.

   Загалом конкретні дії, які має виконувати операторна функція виведення даних, визначає програміст. Але, якщо у Вас виникає бажання дотримуватися професійного стилю програмування, то створена програмістом операторна функція виведення даних повинна тільки виводити інформацію. Проте, завжди не зайве впевнитися в тому, що вона повертає тільки параметр stream.

    Перш ніж переходити до наступного розділу, подумайте, чому операторна функція виведення даних для класу kooClass не була запрограмована так:

// Версія обмеженого застосування (використанню не підлягає).

ostream &operator<<(ostream &stream, kooClass obj)

{

      cout << obj.x << ", ";

      cout << obj.y << ", ";

      cout << obj.z << endl;

      return stream;                 // Повертає посилання на параметр stream

}

   Не важко здогадатися, що у такій версії операторної функції жорстко закодований потік cout. Це обмежує перелік ситуацій, в яких її можна використовувати.

   Отже, програміст повинен передавати операторній функції виведення даних потік, який коректно працює в усіх конкретних випадках. Тільки так можна створити досконалу операторну функцію виведення даних, яка підійде для використання в будь-яких виразах введення-виведення.

  1.  Використання функцій-"друзів" класу для перевантаження операторів виведення даних

    У попередній програмі операторну функцію виведення даних не було визначено як член класу kooClass. Насправді ні будь-яка операторна функція виведення даних, ні функція їх введення не можуть бути членами класу. Справа тут полягає ось в чому. Якщо операторна функція є членом класу, то лівий операнд (що опосередковано передається за допомогою показника this) повинен бути об'єктом класу, який генерує звернення до цієї операторної функції. І це змінити не можна.

    Проте при перевантаженні операторів виведення даних лівий операнд повинен бути потоком, а правий – об'єктом класу, дані якого підлягають виведенню. Отже, перевантажені оператори виведення даних не можуть бути функціями-членами класу.

   У зв'язку з тим, що операторні функції виведення даних не можуть бути членами класу, для якого вони визначаються, то виникає серйозне запитання: як перевантажений оператор виведення даних може отримати доступ до закритих членів класу? У попередній програмі  змінні x, y і z були визначені як відкриті, тому оператор виведення даних без перешкод міг отримати до них доступ. Водночас закриття даних – важлива частина ООП, отже, вимагати, щоб усі дані були відкритими, просто нелогічно.

    Проте існує просте вирішення цього питання – оператор виведення даних можна зробити "другом" класу. Якщо функція є "другом" деякого класу, то вона отримує легальний доступ до його private-даних. Оголошення "другом" класу операторної функції виведення даних продемонструємо на прикладі класу kooClass.

Приклад. Демонстрація механізму використання функцій-"друзів" класу для   

                  перевантаження оператора виведення даних

class kooClass

{

     public:   

             int x, y, z;

             kooClass(int a, int b, int c) { x = a; y = b; z = c; }

             friend ostream &operator<<(ostream &stream, kooClass obj);

};

     // Відображення тривимірних координат x, y, z

     // Перевизначений оператор виведення даних для класу kooClass

ostream &operator<<(ostream &stream, kooClass obj)

{

stream << obj.x << ", ";

stream << obj.y << ", ";

stream << obj.z << endl;

return stream;           // Повертає посилання на параметр stream

}

void main()

{

kooClass ObjA(1, 2, 3), ObjB(3, 4, 5), ObjC(5, 6, 7);

     // Перевантажений оператор виведення даних

cout << ObjA << ObjB << ObjC;

}

   Зверніть увагу на те, що змінні x, y і z у цій версії коду програми є закритими у класі kooClass, проте операторна функція виведення даних звертається до них безпосередньо. У наведеному прикладі якраз і виявляється велика перевага "друзів" класу: оголошуючи операторні функції введення та виведення даних "друзями" класу, для якого вони визначаються, ми тим самим підтримуємо механізм інкапсуляції об'єктно-орієнтованого програмування.

  1.  Створення перевантажених операторів введення даних

    Для перевантаження операторів введення даних використовують аналогічний підхід, який було застосовано при перевизначенні операторів виведення даних. Наприклад, наведений нижче перевантажений оператор введення даних забезпечує введення тривимірних координат. Зверніть увагу на те, що він також виводить відповідне повідомлення для користувача.

   

    // Прийняття тривимірних координат x, y, z

    // Перевантажений оператор введення даних для класу kooClass

istream &operator>>(istream &stream, kooClass &obj)

{

cout << "Введіть координати x, y і z: ";

    // Перевантажений оператор введення даних

stream >> obj.x >> obj.y >> obj.z;

return stream;    // Повертає посилання на параметр stream

}

    Перевантажений оператор введення даних повинен повертати посилання на об'єкт типу istream. Окрім цього, перший параметр повинен бути посиланням на об'єкт типу istream. Цей тип належить потоку, що вказується зліва від оператора ">>". Другий параметр є посиланням на об'єкт, який приймає значення, що вводяться. Оскільки другий параметр – посилання на об'єкт, то його можна модифікувати при введенні інформації.

    Загальний формат перевизначеного оператора введення даних має такий вигляд:

istream &operator>>(istream &stream, objectType &obj)

{

     // код операторної функції введення даних

turn stream;      // Повертає посилання на параметр stream

}

    Особливості використання операторних функцій введення та виведення даних для об'єктів типу kooClass продемонстровано в такому коді програми.

Приклад. Демонстрація механізму перевантаження операторів введення/виведення

                  потокової інформації

 

class kooClass

{

int x, y, z;          // Тривимірні координати

public:

kooClass(int a, int b, int c) { x = a; y = b; z = c; }

friend ostream &operator<<(ostream &stream, kooClass obj);

friend istream &operator>>(istream &stream, kooClass &obj);

};

   // Відображення тривимірних координат x, y, z

   // Перевизначений оператор виведення даних для класу kooClass

ostream &operator<<(ostream &stream, kooClass obj)

{

stream << obj.x << ", ";

stream << obj.y << ", ";

stream << obj.z << endl;

return stream;             // Повертає посилання на параметр stream

}

  // Прийняття тривимірних координат x, y, z

  // Перевизначений оператор введення даних для класу kooClass

istream &operator>>(istream &stream, kooClass &obj)

{

cout << "Введіть координати x, y і z: ";

                      // Перевизначений оператор введення даних

stream >> obj.x >> obj.y >> obj.z;

return stream;              // Повертає посилання на параметр stream

}

void main()

{

kooClass ObjA(1, 2, 3);

cout << ObjA;             // Перевизначений оператор виведення даних

cin >> ObjA;               // Перевизначений оператор введення даних

cout << ObjA;             // Перевизначений оператор виведення даних

}

  Ось як виглядає результат виконання цієї програми:

1, 2, 3

Введіть координати x, y і z: 5 6 7

5, 6, 7

   Подібно до операторних функцій виведення даних, операторні функції їх введення не можуть бути членами класу, для оброблення даних якого вони призначені. Вони можуть бути тільки "друзями" цього класу або просто незалежними операторними функціями. За винятком того, що операторна функція введення даних повертає посилання на об'єкт типу istream, тіло цієї функції може містити все те, що програміст вважає за потрібне у неї помістити. Але логічніше використовувати оператори введення все ж таки за прямим призначенням, тобто для виконання операцій введення даних.

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

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

struct myStruct     // Оголошення типу структури

{

     int count;

     char str[80];

     double balance;

}

то наявну у мові C систему введення-виведення неможливо налаштувати так, щоб вона могла виконувати операції введення-виведення даних безпосередньо над об'єктами типу myStruct. Але, оскільки центром ООП є саме об'єкти, то виникає потреба у тому, щоб у мові програмування C++ функціонувала така система введення-виведення, яку можна було б динамічно "навчати" поводженню з будь-якими об'єктами, що створюються програмістом. Саме тому для мови програмування C++ і було винайдено нову об'єктно-орієнтовану систему введення-виведення. Як уже зазначалося вище, С++-підхід до введення-виведення даних дає змогу перевизначати оператори "<<" і ">>" так, що вони можуть працювати з класами, які створюють програмісти.


 

А также другие работы, которые могут Вас заинтересовать

8450. Школа атомистов 14.86 KB
  Школа атомистов Атомизм был создан представителями досократического периода развития древнегреческой философии Левкиппом и его учеником Демокритом Абдерским. Согласно их учению, существуют только атомы и пустота. Атомы - мельчайшие неделимые, н...
8451. Наука в системе государственных приоритетов 17.43 KB
  Наука в системе государственных приоритетов Наука является производительной силой общества, активно влияет на развитие мирохозяйственных связей и эффективность общественного производства. Именно поэтому она занимает в системе государственных приорит...
8452. Организационные формы управления научным комплексом 16.16 KB
  Организационные формы управления научным комплексом Организационная структура управления научно-техническим комплексом - совокупность научных, научно-производственных и обслуживающих организаций, органов государственного управления научно-технически...
8453. Проблемы переходного процесса национальной экономик России и стран Восточной Европы 25.36 KB
  Проблемы переходного процесса национальной экономик России и стран Восточной Европы РБ находится в процессе перехода к гражданскому демократическому обществу со смешенной соц ориентированной экономикой. Прошедшие годы преобразований (особенно начало...
8454. Anatomy and physiology of CVS 17.05 KB
  Anatomy and physiology of CVS The heart is the main organ of the cardiovascular system and is located in the left side of the mediastinum. There are three layers in the heart: the epicardium, the myocardium and the endocardium. The epicardium covers...
8455. Имитационное моделирование однопроцессорной МИКС, имеющей неограниченную очередь 59.5 KB
  Имитационное моделирование однопроцессорной МИКС, имеющей неограниченную очередь Задание: Построить структуру модели, используя блоки GPSS Составить программу на ASSEMBLERE с заданием параметров, имен элементов системы и обяз...
8456. Понятие экономической безопасности 32 KB
  Понятие экономической безопасности. Экономическая безопасность - это такое состояние нац экономики, которое позволяет обеспечить ее устойчивое функционирование в условиях воздействия внутренних и внешних факторов, достаточное удовлетворен...
8457. Моделирование выхода в Internet по телефонным линиям связи для просмотра электронной почты 103.29 KB
  Моделирование выхода в Internet по телефонным линиям связи для просмотра электронной почты. Цель моделирования - определить необходимый ресурс времени для успешного завершения заданного числа выходов в сеть.
8458. Имитационное моделирование вычислительных процессов и систем 486 KB
  Имитационное моделирование вычислительных процессов и систем Моделирование (дискретных систем). Имитационное моделирование. Концептуальная модель системы. Основы технологии имитационного моделирования. Метод с...