Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 218
Текст из файла (страница 218)
Тот факт, что объекты локализации неизменяемы после создания, очень важен для обеспечения эффективности на этапе выполнения. Это позволяет пользователю вызывать виртуальные функции фасетов и кэшировать возвращаемые значения. Например, беат может знать, какой символ используется в качестве десятичной запятой, или как представляется значение Гкие, не вызывая г!ес!та! 1го1пг() каждый раз при чтении числа и пиепате() при чтении в логическую переменную (9Э.4.2). Только вызов ппЬие () для потока может заставить изменить значения, возвращаемые этими вызовами. 0.2.3. Контексты 9!о(за1() и с!авв)сО Понятие текущей локализации программы поддерживается функцией!оса1е(), возвращающей копию текущей локализации, а также функцией !оса!е::я!оЬа!(), устанавливающей контекст локализации в качестве текущего. Текущую локализацию обычно называют глобальной, имея в виду то, что чаще всего она реализуется с помощью глобального (или статического) объекта.
Глобальная локализация используется неявным образом при инициализации потока, то есть к каждому вновь создаваемому потоку прикрепляется (1тЬие(); 521.1„521.6.3) копия!оса!е () . Изначально, глобальная локализация есть стандартная локализация языка С, 1оса1е::с!паз(с(). Статическая функция-член !оса!е:: я!оЬа1 ( ) позволяет программисту задать контекст локализации, который будет использоваться как глобальный. Эта функция возвращает предыдущий контекст локализации, использовавшийся в качестве глобального контекста, что позволяет при необходимости восстановить его позже.
Например: лойг Г(сопл! 1оеа1еа ту 1ое) ( г1лгкеат 1) п! (лоте пате); 0 к1) п1 прикреплена глобальная локон-Чкя ().2. Класс (оса(е 1019 1оса1е о!6 д!оба! = !оса!в::8!оба! (ту 1ос); //устанавливаеи новую тоб-ную лакал-Чию (увааип у)п2 (готе огйег пате); // к/)п2 прикреплена лакал-пия ту !ос // .. !оса!в:: е1ойИ (оЬ1 8!оба!); //восстанавливаем стар. глоб-ную лакал-Нию 0.2.4. Сравнение строк Сравнение двух строк в соответствии с конкретной локализацией является, наверное, самой распространенной задачей, явно использующей контекст локализации. Поэтому данная операция непосредственно предоставляется классом !оса1е, чтобы избавить пользователей от необходимости создавать собственные функции сравнения из фасета со!!аге (9Э.4.1).
Чтобы функцию сравнения из класса!оса!е можно было использовать непосредственно в качестве предиката 618.4.2), она определена там как орегагог() () . Например: гой1~(гесгогкваупя) ь г, сопл! !оса!еь ту 1оса1е) ( лоув ( у. Ьедчп ( ) ~ г. епа ( ) ) / // ... вогг(г.бея(п(), г.еЫ(),ту !оса(е); //лог(согласно правилом ту 1оса1е //лог( с применением < для сравнения элементов Если в локализации х имеется строка имени, то !оса!е::я!оЬа1(х) также устанавливает глобальную локализацию языка С. Это означает, что если программа на С++ вызывает зависимую от контекста локализации стандартную библиотечную функцию языка'С, то в такой смешанной среде трактовка локализации будет согласованной. Однако если локализация х строки имени не содержит, то неизвестно, влияет ли вызов 1оса1е::я1оЬа1() на глобальный контекстлокализации языка С.
Это означает, что в таком случае программа на языке С++ не может надежным и переносимым образом установить для средств языка С локализацию, которая не была получена от системной среды. Также не существует стандартного способа, которым программа на языке С могла бы установить глобальную локализацию С++ (кроме как вызвать дпя этого функцию С++).
В общем, в смешанной среде программ на языках С и С++ использование дпя языка С глобальной локализации, отличной от д1оЬа1 О, чревато ошибками. Задание глобальной локализации не влияет на уже существующие потоки ввода/вывода; они по-прежнему используют те локализации, которые были закреплены за ними.
Например, на поток 21п! не повлияли последующие манипуляции с глобальной локализацией, в результате которых за потоком ууп2 была закреплена локализация ту 1ос. Манипуляции с глобальной локализацией страдают общим пороком работы с глобальными объектами — очень трудно (если возможно) проконтролировать, на что может повлиять изменение этих объектов. Поэтому вызовы я1оЬа! () лучше всего минимизировать и четко локализовать их в нескольких разделах кода, подчиняющихся простой стратегии этих изменений.
Возможность прикреплять специфические контексты локализации к отдельным потокам (гтЬие (); 521.6.3) существенно упрощает дело, но все равно, изобилие разбросанных по программе явных ссылок на контексты локализации сильно затрудняет сопровождение программы. ЗО2О Приложение (). Локализация По умолчанию, стандартная библиотечная функция золт О использует операцию < с числовыми значениями символьного набора конкретной реализации (5!8.7, 8 1 8.6.3.1). Заметьте, что в рамках контекстов локализации сравниваются объекты типа Ьавйс вп!пй, а не С-строки. 0.3. фасеты Фасеты являются объектами класса, производного от класса !псе! (объявленного в классе 1оса1е): с1азз за1:: !оса!в:: !осе! ( ргогесзей: екрйсй)осе!(з!гя ! г = О); И "г==О" -лакал-я управляет временем жизни этого фасето Ыпиа! -уаст() ! И обратите внимание.
рго(ес(ей деструктор рп'ипе: !осе~ (сопмуасе!й ); гоЫ орегаан= (сопл( Гасе!в ); И представление класса ) И не определен И не определен !г! !'( ! ззггпйь з1, зг!айь ( й нормальный случай: (умолчательный) аргумент О - !оса!е отвечает за удаление: сойаге<сйаг>* р = пев сойазе Ьупате<сйаг> ("р1"); 1оса!е 1ос (!оса!е ( ), р ): й редкий случай: аргумент ! - пользователь отвечает за удаление: вайо!в<айаг>* о = пеы сойаге Ьупате<сйаг> ( "йе", 1); сойазе Ьупате<сйаг> Ьий! ( "кит ); Иеггог невозм но унич ить лок ную перем ую соИазе Ьупате<сйаг> Ьий2 ( "по", 1); У еггог: невозм-но унич-ить лок-ную перем-ую И... И о нельзя удалить: у сода(е булате<слог деструктор рго(ес(ег( й нельзя йе!е(е р; !оса!е управляет удалением *р Операции копирования объявлены закрытыми и оставлены неопределенными для предотвращения копирования (511.2.2).
Класс !асе! спроектирован в качестве базового, и вием нет открытых функций. Его конструктор объявлен как рго!ес!еа, чтобы нельзя было создать обьекты типа «просто !асеан а деструктор объявлен виртуальным для обеспечения корректного уничтожения объектов производных классов.
Предполагается, что оперировать фасетами будут объекты !оса!в при помощи указателей. Нулевой аргумент конструктора класса !асег означает, что!оса1е обязан удалить фасет после исчезновения последней ссылки на него. Напротив, ненулевой аргумент конструктора гарантирует, что!оса1е никогда не удалит фасет. Это значение аргумента предназначено для редкого случая, когда сам программист управляет временем жизни фасета (а не локализация). Например, мы можем попытаться создать объекты стандартного класса фасетов со1!аге Ьупате<сйаг> (5Е).4.1.1) следующим образом: 0.3. Фасеты 1021 Стандартные фасеты полезны, когда управляются контекстами локализации (как базовые классы), и очень редко — в других случаях.
Фасет Ьуиате () является фасетом из именованного локального контекста системной среды (9!Э.2.1). Чтобы можно было осушествлять поиск фасета в рамках контекста локализации функциями Ьаа гасе!() и иве /асег(), для каждого типа фасета должен определяться идентификатор Ы: с!авв вЫ:: !оса1е:: Ы ( риЫгс: Ы(); ргп аге: !д ( сонм Ыа ); гоЫ орегагог= (сопи! !аа )," У представление ) гУ не определен ~У не определен 0.3.1. Доступ к фасетам класса !оса!е Доступ к фасетам класса!оса1е осушествляется с помощью функционального шаблона иж /асе!. С помошью функционального шаблона Ьаз /асег мы можем узнать, имеется ли конкретный фасет в заданном контексте локализации: гетр!иге<с!авв Расе!> Ьоо! Ьав расе! (сапа( !оса!еь ) сйгов ( ); гетр!а(е<с!авв Расе!> сопл! Расе!а иве Расе! (сонм !оса!еь) ! р иопсет генерть Ьаг! сав! Можно считать, что эти шаблонные функции осуществляют поиск параметра шаблона Расею в аргументе 1оса!е.
Можно, однако, взглянуп на функциональный шаблон иве Расе! как на своего рода явное приведение типа от 1оса1е к конкретному фасету. Эта возможность базируется на том, что у!оса1е только один фасет данного типа. Например: Операции копирования объявлены закрытыми и оставлены неопределенными для предотврашения копирования (5! 1.2.2). Класс Ы задуман для того, чтобы пользователь мог определить статический член типа Ы в каждом классе, предоставляющем новый интерфейс фасета (например, см. 5Р.4.1). Внутренние механизмы класса 1оса1е используют Ы для идентификации фасетов (5О.2, 93.3.1). В очевидной реализации Ы используется как индекс вектора указателей на фасеты, реализуя тем самым эффективный тир< Ы,уасег* >.
Поля данных, необходимые лля формирования (производного) фасета определяются в производных классах, а не в самом базовом классеУасе!. Это означает, что программист, определяюший фасет, имеет полный контроль над данными и что любое количество данных может быть задействовано для реализации концепции фасета. Заметьте, что все функции-члены определяемого пользователем фасета должны быть константными. В общем случае, фасеты полагаются неизменяемыми (5Р.2.2).