Стандартные потоки
Выполнение любой программы С++ начинаются с четырьмя предопределенными открытыми потоками, объявленными как объекты классов _withassign в iostream.h следующим образом:
extern istream_withassign cin; extern ostream_withassign cout; extern ostream_withassign cerr; extern ostream_withassign clog;
Их конструкторы вызываются всякий раз при включении iostream.h, но фактическая инициализация выполняется только один раз.
Все эти предопределенные стандартные потоки по умолчанию связаны с терминалом.
Четыре стандартных потока предназначены для:
cin - стандартного ввода;
cout - стандартного вывода;
cerr - стандартного вывода ошибок;
clog - полностью буферизованного вывода ошибок.
В табл. 5 приведено назначение классов потокового ввода-вывода.
ios | Потоковый базовый класс |
---|---|
Потоковые классы ввода | |
istream | Потоковый класс общего назначения для ввода, являющийся базовым классом для других потоков ввода |
ifstream | Потоковый класс для ввода из файла |
istream with assign | Потоковый класс ввода для cin |
istrstream | Потоковый класс для ввода строк |
Потоковые классы вывода | |
ostream | Потоковый класс общего назначения для вывода, являющийся базовым классом для других потоков вывода |
ofstream | Потоковый класс для вывода в файл |
ostream_withassign | Потоковый класс ввода для cout, cerr, and clog |
ostrstream | Потоковый класс для вывода строк |
Потоковые классы ввода-вывода | |
iostream | Потоковый класс общего назначения для ввода-вывода, являющийся базовым классом для других потоков ввода-вывода |
fstream | Потоковый класс для ввода-вывода в файл |
sir stream | Потоковый класс для ввода-вывода строк |
stdiostream | Класс для ввода-вывода в стандартные файлы ввода-вывода |
Классы буферов для потоков | |
Streambuf | Абстрактный базовый класс буфера потока |
filebuf | Класс буфера потока для дисковых файлов |
s trs treambuf | Класс буфера потока для строк |
stdiobuf | Класс буфера потока для стандартных файлов ввода-вывода |
Назначение почти всех классов следует из их названия. Классы группы _withassign являются производными соответствующих потоковых классов без этого окончания. Они перегружают операцию присваивания, что позволяет изменять указатель на используемый классом буфер.
Потоки ввода-вывода C++ предоставляют некоторые преимущества по сравнению с функциями ввода-вывода библиотеки С.
Безопасность типов. Сравним вызов функций библиотеки С и использование стандартных потоков С++. Вызов функции printf() выглядит следующим образом:
#include < stdio.h >
. . .
int n = 12;
char name[ ] = "Вывод строки на экран\n";
printf("%d %s", i, name);
Этот вызов приведет к следующей правильной печати:
12 Вывод строки на экран |
Но если по невнимательности поменять местами аргументы для printf(), ошибка обнаружится только во время исполнения программы. Может произойти все что угодно - от странного вывода до краха системы. Этого не может случиться в случае использования стандартных потоков:
#include < iostream.h >
cout << i <<' ' << name << '\n';
Так как имеются перегруженные версии операции сдвига operator<< (), правая операция всегда будет выполнена. Функция cout<< i вызывает operator<< (int), a cout<< name вызывает operator<< (const char*). Следовательно, использование стандартных потоков является безопасным по типам данных.
Расширяемость для новых типов. Другим преимуществом стандартных потоков С++ является то, что определенные пользователем типы данных могут быть без труда в них встроены. Рассмотрим класс Data, данные которого необходимо печатать:
struct Data {
int x; char* y;};
Все, что нужно сделать, это перегрузить операцию << для нового типа Data. Соответствующая функция operator<< () может быть реализована так:
ostream &operator<< (ostream & out, const Data & р){
return out << p.x << ' ' << p.у;
}
После этого станет возможно осуществлять вывод:
#include < iostream.h >
struct Data {int x; char* y;
Data (int x, char* y){this->x = x; this->y = y;}
};
ostream &operator<< (ostream & out, const Data & p){
return out << p.x <<' '<< p.y;
}
void main(){
Data p(1, "Error");
cout << p<< '\n';
}