Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++ Страуструп.doc
Скачиваний:
4
Добавлен:
18.04.2019
Размер:
2.72 Mб
Скачать

10.5.3 Буферизация

Все операции ввода-вывода были определены без всякой связи с типом

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

алгоритма буферизации. Очевидно, что потоку ostream, привязанному к

строке символов, нужен не такой буфер, как ostream, привязанному к

файлу. Такие вопросы решаются созданием во время инициализации разных

буферов для потоков разных типов. Но существует только один набор

операций над этими типами буферов, поэтому в ostream нет функций, код

которых учитывает различие буферов. Однако, функции, следящие за

переполнением и обращением к пустому буферу, являются виртуальными.

Это хороший пример применения виртуальных функций для единообразной

работы с эквивалентными логически, но различно реализованными

структурами, и они вполне справляются с требуемыми алгоритмами буферизации.

Описание буфера потока в файле <iostream.h> может выглядеть следующим

образом:

class streambuf { // управление буфером потока

protected:

char* base; // начало буфера

char* pptr; // следующий свободный байт

char* gptr; // следующий заполненный байт

char* eptr; // один из указателей на конец буфера

char alloc; // буфер, размещенный с помощью "new"

//...

// Опустошить буфер:

// Вернуть EOF при ошибке, 0 - удача

virtual int overflow(int c = EOF);

// Заполнить буфер:

// Вернуть EOF в случае ошибки или конца входного потока,

// иначе вернуть очередной символ

virtual int underflow();

//...

public:

streambuf();

streambuf(char* p, int l);

virtual ~streambuf();

int snextc() // получить очередной символ

{

return (++gptr==pptr) ? underflow() : *gptr&0377;

}

int allocate(); // отвести память под буфер

//...

};

Подробности реализации класса streambuf приведены здесь только для

полноты представления. Не предполагается, что есть общедоступные

реализации, использующие именно эти имена. Обратите внимание на

определенные здесь указатели, управляющие буфером; с их помощью

простые посимвольные операции с потоком можно определить максимально

эффективно (и причем однократно) как функции-подстановки. Только

функции overflow() и underflow() требует своей реализации для каждого

алгоритма буферизации, например:

class filebuf : public streambuf {

protected:

int fd; // дескриптор файла

char opened; // признак открытия файла

public:

filebuf() { opened = 0; }

filebuf(int nfd, char* p, int l)

: streambuf(p,l) { /* ... */ }

~filebuf() { close(); }

int overflow(int c=EOF);

int underflow();

filebuf* open(char *name, ios::open_mode om);

int close() { /* ... */ }

//...

};

int filebuf::underflow() // заполнить буфер из "fd"

{

if (!opened || allocate()==EOF) return EOF;

int count = read(fd, base, eptr-base);

if (count < 1) return EOF;

gptr = base;

pptr = base + count;

return *gptr & 0377; // &0377 предотвращает размножение знака

}

За дальнейшими подробностями обратитесь к руководству по реализации

класса streambuf.

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