Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 152
Текст из файла (страница 152)
Поэтому, если нужно изменить приемник потока, то вы можете либо изменить буфер (В21.6.4), либо перенаправить вывод при помощи указателя (В6.1.7). Класс Ьзз Ьазе содержит информацию и операции, не зависяшие от типа символов — например, точность для вывода чисел с плавающей запятой.
Поэтому он не обязан быть шаблоном. Кроме типов, определенных с помошью операторов зуреЫе~в !оз Ьазе, библиотека потоков ввода/вывода использует знаковый интегральный тип зггеатз!зе для Глава 21. Потоки представления размера буферов и числа символов, переданных в операциях ввода/вывода.
Аналогично, с помощью оператора <ура<]е]' определяется з<геато9" для представления смешений в потоках и буферах. В файле «оягеат> объявляется несколько стандартных потоков: 1Ф стандартный символьный поток вывода У стандартный небуферированный поток вывода ошибок <У стандартный поток вывода ошибок оз<геат сои« озп еат се<т; оягеа<и с<ос < 0 расширенный поток - аналог сои( (г расширенный поток — аналог сегг ррасширенный поток - аналог с!ое и озп еат шсои« и оягеат ысегг< иоягеат <сс<ое; Потоки сегг и с1о» имеют один и тот же адресат данных; они различаются лишь буферизацией. Поток сои< пишет туда же, куда и я1ои<(921.8), а потоки сеген с1о»вЂ” туда же, куда и я«]егг.
Программист может создавать новые потоки по мере необходимости (521.5). 21.2.2. Вывод встроенных типов Класс аягеат определяет операцию «для управления выводом встроенных типов: <еп<р<а<е<с<ат СЬ, с1аяя Тг = слог <га!<я<СЬ» с<азз Ьаяс оз<геат: Ыг<иа< риЫ<с Ьаяс !оз<СЬ, Тг> ( риЬНс: г)' ... Ьаяс оягеать орега<ог«(яйог< и) < Ьаяс озтеать орега<ог«(1п< и); Ьаз<с аз<<вать орега<ог« (<опе и) < Ьазк оя<геать орега<ог« (ипятпе<< зйог< и) „ Ьаяс оягеать орега<ог« (ипя!еие«<и< и); Ьая!с озтеать орега<ог«(ипз!епе«<опд и) < Ьаяс оз<геать орега<ог« ([<оа<]); Ьаяс оя<геать орега<ог« («оиЫе]) < бал<с оя<геат ь орега<ог«(<опа «оиЫе]) < Ьаяс озиеать орега<ог«(Ьоо! п); Ьая<с оятеат ь орега<ог«(сопя гоЫ* р); У пишет значение указателя Ьаз!с оз<геать р<и(СЬ с) < Упишет с Ьаяс оя<геатЬ вгпе (сопя< СЬ*р, я<геатя!Зе и) бр[0]..р(п-1] <етр<а<е<с<азя СЬ, с<вяз Тг> Ьаяк оя<геат<СЬ, Тг>ь орега<ог«(Ьаяс оз<геат<СЬ, Тг>ь, СЬ) < <етр<а<е<с<азз СЬ, с1азз Тг> Ьазк оз<геат<СЬ, Тг>ь орега<ог«(Ьаяс оятеат<СЬ, Тг>ь, сйаг) Функции ри<() и игйе() просто пишут символы в поток.
Следовательно, операции «для вывода символов не обязательно делать функциями-членами. Их можно опрелелить глобально: 2) .2. Вывод 723 !етр!аге<с1ат Тг> Ьаяс оззгеат<ейаг, Тг>з орега(ог«(Ьаяс оз!геат<сйаг, Тг>З, сйаг); !стр!а!с<с1ат Тг> Ьаис озггеат<сйаг, Тг>з орсгагог« (Ьаяс оззгеат<ейаг, Тг>з, з!алей сйаг); !етр1а!с<с1ат Тг Ьаис оигеат<ейаг, Тг> з орегагог«(Ьаяе озггеат<сйаг, Тг>З, ппз!алей сйаг) Аналогично определяется операция «длл вывода символьных массивов с терминальным нулем: гетр!аге<с1азз Сй, с1ат Тг> Ьаз!е озлеат<СЬ, Тг> з орега!ог« (вайс озггеат<Сй, Тг> з, сопз! Сй*); гетр!а(е<с!азз Сй, сгазз Тг> Ьаз!е озсгеат<Сй, Тг> з орегатг«(Ьаяс озсгеат<Сй, Тг> з, сопз! сйаг*); !сир!а!с<с!азз Тг> Ьаяс озпеат<сйаг, Тг>з прага!ог«(Ьаз!с озпеат<сйаг, Тг>з, сопз! сйаг*); гетргазе<с1азз Тг> Ьаис оигеат<сйаг, Тг>з орега!ог«(Ьаис озпеат<сйаг, Тг>з, сопз! з!апез( сйаг*); !стр!а!е<сйззз Тг> Ьаяе оззгеат<сйаг, Тг> З орегагог«(Ьаис оз(геат<сйаг, Тг> з, сопз! ппз!апеА сйаг*); Операции вывода для типа иг1пя представлены в заголовочном файле <иг!пя> (см.
также В20.3.15). Функция орега!ог«() возврашает ссылку на объект типа озггеат, для которого она была вызвана, так что к атому объекту можно снова применить операцию «. Например; сег « "х="«х; где х имеет тип !пг, интерпретируется следуюшим образом: орегагог«(ест, "х= ") .орега(ог«(х); В частности, зто означает, что когда несколько объектов выводятся в рамках одного оператора языка С++, они будут расположены в ожидаемом порядке — слева направо.
Например: гой! га! (сйаг с) ( сопз« "!п!(' " «с « " ' ) = " «гпз(с) « ' ~п'; Ьм та!а () ( га! ( ' А ' ); га1( 'У' ); ) Для реализации с символами АБС11 эта программа выведет: !и! ( ' А ' ) = 65 !п!('У' ) = 90 Отметим, что символьные литералы имеют тип сйаг (В4.3.1), так что соп!« 'У' выведет букву У, а не число 90.
724 Глава 2 ). Потоки По умолчанию тип Ьоо1 выводится как О или 1. Если вам зто не нравится, можете установить форматирующий флаг Ьоо1а1р«а из <1огиаи)р> Я21.4.6.2) и получить1а(ве или «ие. Например: 1п! тоги () ( сощ «йие « ' ' «1аье « ' тп'; сои! « Ьоо!а(р«о; //использовать символьное представление длл (гие и!о(ле сои! «йие « ' ' «1а1ве « ' ~и' ! В результате вывод будет следующим: '1 0 й ие !а!ее Более точно, флаг Ьоо!а1рйа обеспечивает текстовый вывод, зависящий от текущей локализации (национальных стандартов). Если я установлю нужную (датскую) локализацию (З21.7), то получу следующий вывод: 10 ваиЩа1вй Форматирование чисел с плавающей запятой, вывод целых чисел в разных системах счисления и т.д. рассматриваются в в21.4.
Функция овй еаиз:: орегагог«(сопл! воЫ*) выводит значение указателя в формате, зависящем от машинной архитектуры. Например: !и! тоги () ( гп!* р = пеи 1ио сои! « "1оса1" «ьр « ", Ггее йоге " «р « ' ~и' г выведет на моей машине !оса! Ох7Д)геаз(0, 1гее стоге Ох500с В других системах вывод указателя может быть иным.
21.2.3. Вывод пользовательских типов Рассмотрим пользовательский тип сощр!ех 611.3): с1авв сотр1ех ( риЫ1с: ОоиЫе геа1() соил! (ге!иго ге) ) йоиЫе !таО() сопи /гегоги 1т; ) // ... 21.2. Вывод 725 Операцию вывода «для типа сотр1ех определяем следующим образом: отгеать орегагог«(отгеать з, сопи сотрйхь с) ( гегигп з « ' ( ' «г.геа1() « ', ' «г.(тая () « ' ) ) Теперь для типа сотр!ех операцию «можно использовать точно так же, как для встроенных типов; 1пг та1п () ( сотр1ехх(1,2) г сонг « "х= " « х « ' ~п '; ) На выходе получаем — (1, г) Отметим, что при этом не требуется изменений в объявлении класса оззгеат.
Это очень хорошо, поскольку не будут вноситься изменения в заголовочный файл <оззгеат>. Запрет на внесение изменений в этот файл гарантирует от порчи его структур данных и позволяет осуществлять модИфикацию этого файла без влияния на код пользователя. с1ат Му Ьазе ( риЫгс: 2.. итиа! оззгеать риг(озггеать з) сопля = Ог )' У пишет *Й(я в з оигеать орегагог«(отгеать з, сопя( Му Ьаяеь г) ге<ига г.риз(з) г ) у используется правильная ри(О Здесь функция ризО является виртуальной функцией, обеспечивающей корректность вывода при использовании операции «. 21.2.3.1.
Виртуальные функции вывода Функции-члены класса оигеаш не виртуальные. Операции вывода, добавляемые пользователем, не являкпся функциями-членами, и, значит, они тоже не виртуальные. Одна из причин такого положения дел состоит в желании достичь максимальной эффективности для операции помещения символа в буфер. Это то место, где критически важна производительность, и поэтому нужно обеспечить встраивание функций. А виртуальные функции применяются лля гибкости операций, имеющих дело с переполнением (и переопустошением) буфера 521.6.4).
Тем не менее, иногда программисту нужно вывести объект, для которого известен лишь базовый класс. Поскольку точный тип неизвестен, корректность вывода недостижима путем определения операции «для всех новых типов. Вместо этого в абстрактном базовом классе можно определить виртуальную функцию вывода: Глава 21. Потоки 726 Теперь мы можем написать: с1аяя 5отезуре: риЫГс Му Ьаяе ( риЫ1с: У... озггеата риз(оязгеатя з) сопзтц )' У замещает Му Ьаяе::ри(о коЫ Т(сопят Му Ьазея г, Коте(урез я) У используется «, вызывающая правил~кую ригО ( сонг « г « зг ) Таким образом виртуальная функция риг() интегрируется в программный каркас, формируемый классом овгеащ и операциями «. Это полезный универсальный прием для введения операций, которые ведут себя как виртуальные функции с выбором на этапе выполнения на основе их второго аргумента. 21.3.1.
Потоки ввода Аналогично классу Ьаяк ояггеат (521.2.1) класс Ьаяс мггеат определен в заголовочном файле <1яггеат>, содержащем те средства файла <гоев еаеп, которые относятся к вводу: гетргаге<сгаяя СЬ, егозя Тг = сваг егаая<СЬ» сгазз зЫ::Ьаяс 1зггеат: ггггиа1 риЫ1с Ьаяс 1оя<СЬ, Тг> ( риЫ(с: итиа1 -Ьаяс яггеат (); У... Базовый класс Ьаяс Ыя описан в 521.2.1. Два стандартных потока ввода сбя и ис)и приведены в <1озггеаеп>: гуредеТЬаяк 1зггеат<сааг> 1япеат; гуредег Ьазгс Ыегеат < ислаг 1> нязггеат; 1ззгеат с(п; У стандартный поток ввода символов типа сааг нвяггеат юст) Р стандартный поток ввода символов типа исаак г Поток сгп читает из того же источника, что и мйи (521.8).