67370

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

Лекция

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

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

Украинкский

2014-09-07

85.5 KB

13 чел.

Лекція № 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++ і було винайдено нову об'єктно-орієнтовану систему введення-виведення. Як уже зазначалося вище, С++-підхід до введення-виведення даних дає змогу перевизначати оператори "<<" і ">>" так, що вони можуть працювати з класами, які створюють програмісти.


 

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

21707. Разделы модуля «Базовые понятия. Методы извлечения знаний» 368 KB
  Методы извлечения знаний [1] История и этапы развития искусственного интеллекта [2] Подходы к созданию систем искусственного интеллекта [3] Искусственный интеллект в России [4] Направления развития искусственного интеллекта [5] Основные определения [6] Методы извлечения знаний [7] Классификация методов извлечения знаний [8] Пассивные методы [9] Наблюдения [10] Анализ протоколов мыслей вслух [11] Лекции [12] Активные методы [13] Активные индивидуальные методы [14] Анкетирование [15] Интервью [16] Свободный диалог [17] Активные групповые методы...
21708. Модуль Жизненный цикл интеллектуальной системы 147.5 KB
  2] Этап 2: Разработка прототипной системы [1.4] Этап 4: Оценка системы [1.5] Этап 5: Стыковка системы [1.
21709. Модуль Методы представления знаний: Нечеткая логика 192 KB
  Математический аппарат Характеристикой нечеткого множества выступает функция принадлежности Membership Function. Обозначим через MFcx степень принадлежности к нечеткому множеству C представляющей собой обобщение понятия характеристической функции обычного множества. Значение MFcx=0 означает отсутствие принадлежности к множеству 1 полную принадлежность. Так чай с температурой 60 С принадлежит к множеству 'Горячий' со степенью принадлежности 080.
21711. Оценка вероятностей возможных последствий от нарушений электроснабжения потребителей 181.5 KB
  Оценка вероятностей возможных последствий от нарушений электроснабжения потребителей Для решения широкого класса задач эксплуатации и проектирования с учётом фактора надёжности необходимо определение вероятностей возникновения возможных последствий от нарушения электроснабжения потребителей которые сводятся к следующим: вероятность возникновения катастрофических и аварийных ситуаций исследование которых необходимо для нормирования надёжности электроснабжения; вероятность возникновения отдельных составляющих ущерба их величина и...
21712. ИСПЫТАНИЯ НА НАДЕЖНОСТЬ ЭМС. КОНТРОЛЬНЫЕ ИСПЫТАНИЯ 2.49 MB
  Показатели надежности экспериментальными методами могут быть получены по результатам либо испытаний специальных или совмещенных либо наблюдением за функционированием объекта в условиях эксплуатации. Методы испытаний организуются специально с целью определения показателей надежности объем их обычно заранее планируется условия функционирования объектов устанавливаются исходя из требований оценки конкретных показателей. Показатели надежности таких объектов оцениваются в основном либо по результатам совмещенных испытаний при которых...
21713. СТАТИСТИЧЕСКИЕ МЕТОДЫ ОЦЕНКИ, АНАЛИЗА И КОНТРОЛЯ НАДЕЖНОСТИ 358.5 KB
  Сбор информации об отказе элементов технических систем В общем комплексе мероприятий по обеспечению надёжности любого изделия сбор статистической информации об отказах и оценка показателей надёжности в условиях эксплуатации являются последним заключительным этапом. При этом появляется возможность оценить реальные значения показателей надежности и следовательно оценить эффективность мероприятий по обеспечению надёжности на всех этапах проектирование производство испытания монтаж эксплуатация. Поэтому особое значение приобретает вопрос...
21714. ИСПЫТАНИЯ НА НАДЕЖНОСТЬ ЭМС. ОПРЕДЕЛИТЕЛЬНЫЕ ИСПЫТАНИЯ 3.06 MB
  При определительных испытаниях могут оцениваться законы распределения отказов и их параметры. При определительных испытаниях могут оцениваться законы распределения отказов и их параметры. Однако существует универсальный план испытаний позволяющий по единой методике проводить статистическую оценку величины Р для изделий с любым законом распределения. Полученные данные по отказам изделий в результате испытаний или по данным эксплуатации подвергаются статистической обработке для получения следующих результатов: определения вида функции...
21715. Планирование эксперимента при ускоренных испытаниях электрических машин 102 KB
  ТЕМА № 2 Регрессионный анализ установившихся режимов электрической системы Для этой цели целесообразно использование регрессионного моделирования сложной системы. При этом с использованием имеющихся программ расчета установившегося режима на ЭВМ проводятся целенаправленные исследования в результате которых получаются регрессионные модели для анализа или управления. Такие модели могут быть получены при регрессионном анализе или методом планирования многофакторного эксперимента МПЭ. При этом для построения линейных моделей используется полный...