Перегрузка операторов вставки и извлечения — КиберПедия 

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

Перегрузка операторов вставки и извлечения

2021-12-07 46
Перегрузка операторов вставки и извлечения 0.00 из 5.00 0 оценок
Заказать работу

Выполняя запись и чтение с помощью потоков ввода-вывода, удобно вместо относительно громоздких предложений с потоковыми функциями write () и read () использовать операторы вставки в поток (<<) и извлечения из потока (>>). В языке C++ эти операторы служат для побитового сдвига данных влево или вправо на заданное число двоичных разрядов. Однако в потоковых классах ostream и istream (а также и в производных от них) они перегружены и обозначают совсем другие операции: пересылку указанного данного в поток (оператор <<) и, наоборот, получение из потока очередного данного с сохранением его в указанной переменной (оператор <<). Операторы << и >> всегда указываются справа от переменной, обозначающей объект потока:

streamout << data1;// Вывод данного из переменной data 1 в поток

              // вывода streamout

streamin >> data2; // Извлечение данного из потока ввода streamin

              // в переменную data 2

Большим достоинством операторов вставки и извлечения является возможность их объединения в цепочки:

streamout << data1 << data2 << data3;// Вывод в поток

              // streamout последовательно трех данных

Операторы << и >> широко использовались в приложениях MS-DOS и все еще используются в консольных приложениях Window, однако их непосредственное применение в современных прикладных программах затруднительно, так как они осуществляют автоматическое преобразование числовых данных в символьные строки и наоборот. Так, например, фрагмент

int data = 125;

stream << data

выполнит запись в файл, связанный с потоком stream, не четырех байтов, содержащих число 125 в двоичной форме, а трех байтов с кодами 0x31, 0x32 и 0x35, представляющих собой символьные представления десятичных цифр 1, 2 и 5.

Для того чтобы с помощью операторов вставки и извлечения осуществлять запись и чтение числовых данных в машинном формате (что обычно и требуется в прикладных программах обработки результатов экспериментов или моделирования), необходимо перегрузить эти операторы применительно к составу прикладного класса. Сущность перегрузки заключается в том, что в операторную функцию, перегружающую соответствующий оператор, включается необходимое число вызовов потоковых функций read () или write (), каждый из которых обеспечивает передачу порции однородных данных.

Рассмотрим пример перегрузки операторов вставки и извлечения применительно к простому классу с именем Point 2 D, в состав которого входят два целых числа (представляющие собой, например, координаты точки на экране).

/* Файл POINT.H*/

class Point2D{

public:

int x,y;

Point2D(int xx,int yy){// Конструктор-инициализатор

x=xx;y=yy;

}

Point2D(){}// Конструктор по умолчанию (без параметров)

// Включим в класс прототипы операторных функций для перегрузки

friend ofstream& operator << (ofstream&, Point2D&);

friend ifstream& operator >> (ifstream&, Point2D&);

};

/* Файл POINT.CPP*/

#include <windows.h>

#include <fstream.h>// Для работы с потоками ввода-вывода

// Определим операторную функцию для перегрузки оператора <<

ofstream& operator << (ofstream& strm, Point2D& obj){

strm.write((char*)&obj.x,4);

strm.write((char*)&obj.y,4);

return strm;

}

// Определим операторную функцию для перегрузки оператора >>

ifstream& operator >> (ifstream& strm, Point2D& obj){

strm.read((char*)&obj.x,4);

strm.read((char*)&obj.y,4);

return strm;

}

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int){

Point2D pt1(100,200);// Создадим экземпляр класса Point2 D

Point2D pt2;// Создадим пустой объект для чтения в него

ofstream outpt("test.dat",ios::binary);// Создадим поток

                  // вывода, связанный с файлом TEST. DAT

outpt<<pt1;// Вывод объекта pt1 в файл TEST. DAT

outpt.close();// Закроем поток и файл

ifstream inpt("test.dat",ios::binary); // Создаедим поток

                  // ввода, связанный с файлом TEST. DAT

inpt>>pt2; // Чтение данных из файла TEST. DAT в объект pt2

inpt.close();// Закроем поток и файл

char txt[200];

wsprintf(txt,"%d %d",pt2.x,pt2.y);// Преобразуем в строку

MessageBox(NULL,txt,"Из файла",MB_OK);// и выведем в окно

return 0;

}

Прикладной класс Point 2 D определен, как это обычно и делается, в заголовочном файле POINT. H. Данные-члены класса x и y для простоты помещены в открытую секцию, чтобы к ним можно было обратиться из программы (в функции wsprintf ()). В состав класса, кроме данных, входят два перегруженных конструктора (конструктор-инициализатор и конструктор по умолчанию), а также прототипы операторных функций operator <<() и operator >>(), с помощью которых мы перегрузим операторы вставки и извлечен

Из прототипа функции перегрузки оператора вставки в поток

friend ofstream& operator << (ofstream&, Point2D&);

видно, что она принимает в качестве параметров ссылку на объект класса ofstream, в который она будет пересылать данные, а также ссылку на объект прикладного класса (Point 2 D в данном случае), который будет пересылаться в поток. Напомним, что при использовании перегруженного оператора

outpt << pt1;

оператор << вызывается для объекта, стоящего слева от него, а объект, стоящий справа, поступает в операторную функцию в качестве аргумента. Оба параметра операторная функция должна получать по ссылке (обозначения ofstream & и Point 2 D &).

Для того, чтобы оператор << мог использоваться в цепочечных операциях, функция возвращает ссылку на объект потока ofstream.

Описатель friend определяет, что наша функция является дружественной для класса, в котором она описана, т. е. для класса Point 2 D. Дружественные функции замечательны тем, что, сами не будучи членами класса, они имеют доступ к закрытым членам класса. Правда, в нашем классе Point 2 D все члены открыты, однако сокрытие данных является важной концепцией объектно-ориентированного программирования, и вынужденное открытие данных является серьезным нарушением его принципов.


Но зачем нужен описатель friend? Почему нельзя объявить перегруженный оператор просто членом класса? Ведь в этом случае он также будет иметь доступ к закрытым членам класса. Оказывается, перегруженные операторы >> и << не могут быть членами класса. Это объясняется тем, что у любого перегруженного оператора-члена класса левым операндом должен быть объект этого класса. Изменить это требование нельзя. В нашем же случае левым операндом оператора << является поток (outpt в приведенном выше примере), а объект класса, для которого осуществляется операция вывода, поступает в операторную функцию через правый параметр. Такой оператор не может быть членом класса, однако его можно объявить другом класса. В этом случае отмеченное выше ограничение на тип левого операнда отменяется и, в то же время, оператор-друг класса имеет доступ ко всем его закрытым членам.

Все сказанное относится и к оператору извлечения из потока >>.

Операторные функции определены в файле POINT.CPP. Еще раз можно отметить, что хотя прототипы этих функций объявлены в составе класса Point 2 D, сами они не являются членами этого класса (в заголовке каждой функции перед ее именем не указана принадлежность к классу Point 2 D::).

Каждая операторная функция включает в себя последовательность вызовов функций read () или write (), вызываемых для левого операнда (потока) с передачей им по очереди всех членов класса, которые требуется поместить в поток или извлечь из него. В нашем примере это переменные x и y, принадлежащие объекту, являющемуся правым операндом перегружаемых операторов (и, соответственно, вторым аргументом операторных функций). Особенности использования функций read () и write () были описаны выше.

В главной функции WinMain () создаются два объекта класса Point 2 D (один – инициализированный для записи его на диск, а другой – “пустой” для чтения в него данных с диска), открывается поток, связанный с файлом POINT.DAT и одним предложением

outpt << pt1;// Вывод объекта pt1 в файл TEST. DAT

осуществляется вывод в файл всех данных, входящих в объект. Далее файл закрывается, открывается снова для чтения и предложением

inpt >> pt2; // Чтение данных из файла TEST. DAT в объект pt2

все записанные на диск данные читаются в объект pt 2. В заключительных предложениях прочитанные данные преобразуются в символьную форму и выводятся в окно сообщения (рис. 6.2).

Рис. 6.2. Контрольный вывод в окно сообщения данных из файла

Живучесть объектов


Поделиться с друзьями:

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.014 с.