Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c++book1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
2 Мб
Скачать
☆

8.2.5 Виртуальная Функция Вывода

Иногда функция вывода должна быть virtual. Рассмотрим пример класса shape, который дает понятие фигуры (#1.18):

class shape (*

// ...

public:

// ...

virtual void draw(ostream& s); // рисует "this" на "s" *);

class circle : public shape (*

int radius;

public:

// ...

void draw(ostream&);

*);

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

Чтобы поддерживать для таких классов стандартную пара­дигму вывода, операция << определяется так:

ostream& operator<<(ostream& s, shape* p)

(*

p->draw(s);

return s;

*)

Если next - итератор типа определенного в #7.3.3, то список фигур распечатывается например так:

while ( p = next() ) cout << p;

8.3 Файлы и Потоки

Потоки обычно связаны с файлами. Библиотека потоков соз­дает стандартный поток ввода cin, стандартный поток вывода cout и стандартный поток ошибок cerr. Программист может отк­рывать другие файлы и создавать для них потоки.

8.3.1 Инициализация Потоков Вывода

ostream имеет конструкторы:

class ostream (*

// ...

ostream(streambuf* s); // связывает с буфером потока

ostream(int fd); // связывание для файла

ostream(int size, char* p); // связывает с вектором

*);

Главная работа этих конструкторов - связывать с потоком буфер. streambuf - класс, управляющий буферами; он описывает­ся в #8.6, как и класс filebuf, управляющий streambuf для файла. Класс filebuf является производным от класса streambuf.

Описание стандартных потоков вывода cout и cerr, которое находится в исходных кодах библиотеки потоков ввода/вывода, выглядит так:

// описать подходящее пространство буфера

char cout_buf[BUFSIZE]

// сделать "filebuf" для управления этим пространством

//связать его с UNIX'овским потоком вывода 1 (уже открытым)

filebuf cout_file(1,cout_buf,BUFSIZE);

// сделать ostream, обеспечивая пользовательский интерфейс

ostream cout(&cout_file);

char cerr_buf[1];

// длина 0, то есть, небуферизованный

// UNIX'овский поток вывода 2 (уже открытый)

filebuf cerr_file(2,cerr_buf,0);

ostream cerr(&cerr_file);

Примеры двух других конструкторов ostream можно найти в #8.3.3 и #8.5.

8.3.2 Закрытие Потоков Вывода

Деструктор для ostream сбрасывает буфер с помощью откры­того члена функции ostream::flush():

ostream::~ostream()

(*

flush(); // сброс

*)

Сбросить буфер можно также и явно. Например:

cout.flush();

8.3.3 Открытие Файлов

Точные детали того, как открываются и закрываются файлы, различаются в разных операционных системах и здесь подробно не описываются. Поскольку после включения <stream.h> стано­вятся доступны cin, cout и cerr, во многих (если не во всех) программах не нужно держать код для открытия файлов. Вот, од­нако, программа, которая открывает два файла, заданные как параметры командной строки, и копирует первый во второй:

#include <stream.h>

void error(char* s, char* s2)

(*

cerr << s << " " << s2 << "\n";

exit(1);

*)

main(int argc, char* argv[])

(*

if (argc != 3) error("неверное число параметров","");

filebuf f1;

if (f1.open(argv[1],input) == 0)

error("не могу открыть входной файл",argv[1]); istream from(&f1);

filebuf f2;

if (f2.open(argv[2],output) == 0)

error("не могу создать выходной файл",argv[2]); ostream to(&f2);

char ch;

while (from.get(ch)) to.put(ch);

if (!from.eof() !! to.bad())

error("случилось нечто странное","");

*)

Последовательность действий при создании ostream для именованного файла та же, что используется для стандартных потоков: (1) сначала создается буфер (здесь это делается пос­редством описания filebuf); (2) затем к нему подсоединяется файл (здесь это делается посредством открытия файла с помощью функции filebuf::open()); и, накрнец, (3) создается сам ostream с filebuf в качестве параметра. Потоки ввода обраба­тываются аналогично.

Файл может открываться в одной из двух мод:

enum open_mode (* input, output *);

Действие filebuf::open() возвращает 0, если не может от­крыть файл в соответствие с требованием. Если пользователь пытается открыть файл, которого не существует для output, он будет создан.

Перед завершением программа проверяет, находятся ли по­токи в приемлемом состоянии (см. #8.4.2). При завершении программы открытые файлы неявно закрываются.

Файл можно также открыть одновременно для чтения и запи­си, но в тех случаях, когда это оказывается необходимо, пара­дигма потоков редко оказывается идеальной. Часто лучше расс­матривать такой файл как вектор (гигантских размеров). Можно определить тип, который позволяет программе обрабатывать файл как вектор, см. Упражнения 8- 10.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]