Глава 13. Обзор потоков ввода-вывода___________________________323
Эта программа демонстрирует, как с помощью элемента streainbuf можно использовать внутренние механизмы потоков. В приведенном примере мы, грубо говоря, вытаскиваем наружу конец буфера потока консольного ввода и методично опустошаем его вплоть до тех пор, когда пользователь прекратит ввод нажатием клавиш <Ctrl>+<Z>. Нас здесь интересует, разумеется, не результат работы этой программы, а возможность манипуляций с потоками посредством объекта streanibuf.
В этом примере встречаются имена rdbuf и sbumpc. Функция rdbuf возвращает указатель на элемент потока streambuf, a sbumpc извлекает из потока текущий символ. Нет никакого смысла загромождать книгу листингами для каждого элемента каждого класса, поскольку по всем вопросам исчерпывающие ответы можно найти в файлах помощи Borland C++. Разработчиками фирмы Borland была проделана гигантская работа по документированию их продукта, поэтому прежде чем писать свои собственные функции, не поленитесь пошарить по справочной системе — может статься, вы найдете в ней готовое решение.
В следующем разделе обсуждается тема, касающаяся одновременно и потоков ввода-вывода, и перегрузки операций. Возможно, вам стоит подкрепить свою теоретическую подготовку чтением глав 14, 15 и 16.
Перегрузка потоковых операций
Будем считать, что вы вняли совету и ознакомились с главами 14, 15 и 16, а может быть, вы ни в чьих советах не нуждаетесь. В общем, вы представляете себе, что такое перегрузка операций и как она работает. Теперь давайте поговорим о перегружаемых потоковых операциях. Создаваемые вами сложные производные типы данных могут счесть себя несправедливо обойденными, если не предоставить им возможность работать с операциями подобно базовым типам. В этом случае вы можете уверенно заявить, что хваленая объектная ориентированность C++ неполноценна. Но это не так.
C++ предоставляет программистам возможность "обучать" новые типы — классы и структуры — работать с операциями так же, как это делают встроенные типы. Операции вроде 1+2 относятся к самым азам программирования, поэтому иметь такую же поддержку для данных пользовательских типов крайне заманчиво.
Не особенно сложно представить себе, как это осуществить. Во-первых, язык должен располагать средствами распознавания замаскированных оператор-функций. Поскольку все это он умеет, нам нужно всего-навсего знать грамматику и соблюдать соответствие количества операндов операции. Поскольку речь сейчас идет об операциях для потоков ввода-вывода « и », то нам известно, что они двухместные и что число аргументов для них должно быть равно двум.
Наконец нам надо разобраться, что должны делать потоковые операции, а также выяснить порядок и расположение их аргументов.