На рис. 11.10 также показано, как эти классы взаимодействуют с объектно-ориентированным каналом. Рассмотрим подробнее, как итератор ostream_iterator используется с объектом класса ostream. Если инкрементируется указатель, мы ожидаем, что он будет указывать на следующую область памяти. Если же инкрементируется итератор ostream_iterator, он переме
Тогда X является объектом типа ostream_iterator. При выполнении операции инкремента X++; итератор X перейдет к слелую
*X = Y;
значение Y будет отображено на стандартном устройстве вывода. Дело в том, что оператор присваивания "=" перегружен дл
ostream_iterator
будет создан объект X с использованием аргумента cout. Второй аргумент в конструкторе является разделителем, который автоматически будет размещаться после каждого int -значения, вставляемого в поток данных. Объявление итератора ostream_iterator выглядит следующим образом (листинг 11.22).
// Листинг 11.22. Объявление класса ostream_iterator
template
protected:
ostream* _M_stream;
const char* _M_string; public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
ostream_iterator(ostream& _s) : _M_stream(&_s),_M_string(0) {}
ostream_iterator(ostream& _s, const char* _с): _M_s tream (&_s) , _M_string (_с) { }
ostream_iterator<_Tp>& operator=(const _Tp& _value) {
*_M_stream << _value;
if (_M_string){
*_M_stream << _M_string;
return *this;
}
ostream_iterator<_Tp>& operator*() { return *this; }
ostream_iterator<_Tp>& operator++() { return *this; }
ostream_iterator<_Tp>& operator++(int) { return *this; }
};
Конструктор класса ostream_iterator принимает ссылку на объект класса ostream. Класс ostream_iterator находится с классом ostream в отношении агрегирования. Назначение класса istream_iterator прямо противоположно классу ostream_iterator. Он используется с объектами класса istream (а не с объектами класса ostream). Если объекты классов istream_iterator и ostream_iterator связаны с iostream-объектами, которые в свою очередь связаны с файловыми дескрипторами канала, то при каждом инкрементировании итератора типа istream_iterator из канала будут считываться данные, а при каждом инкрементировании итератора типа ostream_iterator в канал будут записываться данные. Чтобы продемонстрировать, как эти компоненты работают вместе, рассмотрим две программы (11.2 и 11.2.1), в которых используются анонимные каналы связи. Про-грамма11.2 представляет родительский процесс, а программа11.2.1— сыновний. В»родительской» части для создания сыновнего процесса используются системные функции fork() и execl (). При том, что файловые дескрипторы наследуются сыновним процессом, их значения незамедлительно становятся достоянием программы 11.2.1 благодаря вызовуфункции execl() .
// Программа 11.2
10 int main(int argc, char *argv[])
11 {
12
13 int Size,Pid,Status,Fdl[2],Fd2[2];
14 pipe(Fdl); pipe(Fd2);
15 strstream Buffer;
16 char Value[50];
17 float Data;
18 vector
19 Buffer « Fdl[0] « ends;
20 Buffer » Value;
21 setenv(«Fdin»,Value,l);
22 Buffer.clear();
23 Buffer « Fd2[l] « ends;
24 Buffer » Value;
25 setenv(«Fdout»,Value,l);