Использование перегрузки операций для ввода-вывода объектов
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Язык Си++ предоставляет возможность использования 2-х способов организации ввода данных встроенных типов.

1-ый способ. Использование средств Си. В этом случае используются библиотечные функции ввода-вывода. Одним из фактических параметров, которые необходимо задавать при вызове этих функций является фактический параметр, который задает сведения о форматах, используемом при вводе-выводе. Структура этого параметра является достаточно громоздкой и обычно имеет большое количество ошибок. Кроме того, существуют определенные правила, по которым задаются адреса данных. Например, при вводе требуется задавать адреса данных. Невыполнение этого требования приводит также к ошибкам, поиск которых также является достаточно сложным.

2-ой способ. В этом случае для организации ввода-вывода созданы стандартные объекты cin (для ввода) класса istream и cout(для вывода) класса ostream. В этих классах для каждого встроенного типа данных определена собственная функция ввода или вывода. Отличие от первого способа заключается в том, что эти функции представлены функциями, которые перегружают 2 встроенные операций сдвига <<(вывод) и >>(ввод). То есть, в этом случае используются функции operator<<(вывод) и operator>>(ввод). При этом, как и в других случаях перегрузки, транслятор использует вызов той перегруженной функции, которая совпадает по типу фактического параметра.

 

Например, ввод целого числа а, строки s символов записывается как

 сin>>a>>>s; // в одной строке указаны данные разных типов

Транслятор это выражение интерпретирует как

(cin.operator>>(a)).operator>>(s)

где cin - стандартный объект, для которого определены функции-operator>> по каждому встроенному типу данных. В самом операторе ввода не требуется указывать тип данных, транслятор определяет его из описания.

 

Например, вывод целого числа а, строки “hhhhh” s записывается как

cout<<a<<”hhhhh”<<a; //// в одной строке указаны данные разных типов

 Транслятор это выражение интерпретирует как

(сout.operator<<(a)).operator<<(s)

где cout – стандартный объект, для которого определены функции-operator << по каждому встроенному типу данных. В самом операторе вывода также не требуется указывать тип данных, транслятор определяет его из описания.

 

При организации ввода-вывода объектов, также возможно использование двух способов.

1-ый способ. Использование специальных член-функций ввода-вывода, которые вызываются для каждого объекта обычным способом и используют стандартные средства вывода встроенных типов.

2-ой способ. Желательно обеспечить ввод-вывод объектов по 2-ому способу, который используется для встроенных типов; при этом также необходимо, чтобы в одной строке оператора можно было бы указывать данные разных типов, включая объекты.

При реализации этого способа необходимо выполнить следующую последовательность действий.

1.- перегрузить соответствующую операцию сдвига (<< или >>) для класса, который описывает объект.

Для этого в этом классе должна быть объявлена дружественная функция operator << или operator >> с двумя параметрами.

1-ый параметр указывает имя формального параметра, который задает стандартный объект, используемый в операторах ввода-вывода оператора функции operator;

2- ой параметр задает имя формального параметра, который задает имя и тип объекта, для которого выполняется дружественная функция.

Функция operator должна возвращать ссылку на объект, представленный 1-ым параметром для того, чтобы можно было бы записывать операции ввода-вывода в одну строку.

Дружественная функция operator описывается вне класса как обычная функция. В ней описываются алгоритм ввода членов-данных объекта с любыми видами обработки.

 

1-ый пример

Эта программа представляет пример переопределения встроенной операции сдвига << языка СИ++ для вывода членов-данных объектов определенного класса: строки и длины строки.

Эта перегруженная операция используется в одной строке вывода с операцией вывода строки, которая представляет данные встроенного типа.

 

*#include <string.h>

#include <iostream.h>

#include <conio.h>

class y // заголовок класса

{ int n; // длина строки

char *s; // указатель строки

friend ostream& operator <<(ostream& , y); /* объявление дружественной функции-оператора << для класса y */

 public:

y(char* s1) // конструктор

{ n=strlen(s1);

s=new char [n+1]; // запрос памяти для строки

strcpy(s,s1);}

};// конец определения класса

 

/* перегруженная операция вывода данных объекта класса y; дружественная функция*/

 ostream& operator<<(ostream& r, y h)

 { return r<<"lenght of string "<<h.n<<" string "<<h.s<<endl;};

 

 

int main()// главная функция

{ clrscr();

 y iop ("ggggg"); // определение объекта iop класса y

 cout<<"output "<<iop<<'\n';/*вывод строки "output"и содержимого объекта iop*/

 getche();

 return 0;

 }

 

Замечание

При реализации оператора cout<<"output "<<iop<<'\n', записанного в программе, на самом деле выполняется последовательностью сцепленных операторов operator((cout.operator<<(“output”)),iop).operator(‘\n’);

В этом случае для вывода строки “output” выполняется оператор cout.operator<<(“output”);

Для вывода объекта iop выполняется оператор operator<<(cout,iop); где формальному параметру r соответствует фактический параметр cout, который задает имя стандартного объекта вывода.

В этом случае для вывода символа ‘\n’ выполняется оператор cout.operator<<('\n').

 

 

2-ой пример

Программа этого примера использует условие предыдущего примера; отличие состоит в том, что операция вывода переопределена не для одного объекта, а для массива объектов. Поэтому имеется возможность выводить в одной строке не отдельные элементы, а сразу весь массив.(но с одним и тем же размером массива).

#include <string.h>

#include <iostream.h>

#include <conio.h>

class y

{ int n;

char *s;

 friend ostream& operator <<(ostream& , y*);// объявление дружественной функции

 public: //конструктор

 y(char* s1)

{ n=strlen(s1);

s=new char [n+1];

strcpy(s,s1);}

};// конец определения класса

// переопределенная операция << вывода массива объектов

 ostream& operator<<(ostream& r, y* h)

 { for (int i=0;i<2; i++)

{r<<"lenght of string "<<((h+i)->n)<<" string "<<(h+i)->s<<endl;};

return r;}

 

int main()// главная функция

 

{ clrscr();

 y iop[2]={y("ggggg"),y("uuuuuuu")}; /* инициализация массива из 2-х объектов*/

 cout<<"output \n "<<iop<<'\n'; // вывод строки и массива двух объектов

 getche();

 return 0;

 }

 

3- ий пример

В дополнение к предыдущему примеру в программе этого примера переопределяется для объекта той же структуры встроенная операция >> для ввода данных объекта. В переопределенной функции реализуется ввод данных в промежуточный буфер и далее передача веденных данных в объект; в основной программе обращение к этой операции производится для каждого элемента определенного массива объектов. Отличительной особенностью является то, что 2-ой аргумент у переопределяющей функции ввода operator >> задается ссылкой, так как при вводе должно быть выполнено изменение данных, т.е. должен быть передан адрес.

 

 

#include <string.h>

#include <iostream.h>

#include <conio.h>

class y // заголовок класса y

{ int n;

char *s;

// объявление 2-х дружественных функций для ввода и вывода данных

 friend ostream& operator <<(ostream& , y);

 friend istream& operator >>(istream& , y&);

 public:

 //конструктор

 y(char* s1)

{ n=strlen(s1)+1;

s=new char [n];

strcpy(s,s1);}

};// конец определения класса

//переопределение операции вывода объекта

 ostream& operator<<(ostream& r, y h)

{ r<<"lenght of string "<<((h.n)-1)<<" string "<<h.s<<endl;

return r;}

// переопределение операции ввода объекта

 istream& operator>>(istream& r, y& h)

 { char buf[255];

cout <<"vvedite stroku \n";

r>>buf;

h.n=strlen(buf)+1;

h.s=new char [h.n];

strcpy(h.s,buf);

return r;}

// основная программа для ввода и вывода объектов с использованием

//перегруженных операций ввода и вывода

int main()

{ clrscr();

 y iop[2]={y("ggggg"),y("uuuuuuu")};//инициализация массива объектов

 

 for (int i=0; i<2; i++)

cout<<"output \n "<<iop[i]<<'\n';// вывод i-го объекта

cout<<"vvedite obekti \n";

 for ( i=0; i<2; i++)

cin>>iop[i]; //ввод i-го объекта

 for ( i=0; i<2; i++)

cout<<"output \n "<<iop[i]<<'\n'; // вывод i-го объекта

 getche();

 return 0;

 }

 

2. Индивидуальные задания

Разработать 6 программ обработки набора объектов. Все программы должны реализовать единый алгоритм обработки, указанный в разделе варианты заданий темы № 1.

Для каждого объекта задана характеристика: данные и функции, которые могут обрабатывать эти данные. В индивидуальном задании эти характеристики соответственно указаны в пунктах: исходные данные и функции.

 Программы 2-6 отличаются используемыми программными средствами, которые определены в каждой теме.

 

Дата: 2019-03-05, просмотров: 208.