Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 205
Текст из файла (страница 205)
Ранние реализации стандартной библиотеки были неполными. Например, некоторые имеют контейнеры, которые не поддерживают распределители памяти, а другие требуют, чтобы распрелелители памяти были явно указаны для каждого класса. Схожие проблемы возникают для других «аргументов, определяющих политику а лгоритма», таких как критерии сравнения. Например: 11зг<гпГ>10 1/правильно, нонекоториереалнзации п<ребуют распределителя пал~яти 11зг<гпг, айосаго< Ьц» 02; //правильно, но некоторые реализации // не реализуют распределителей памяти тар<з1ггпу, йесогс1> т1; // правильно, но некоторыв реализации требуют // указиння оперся<и <меньше» (1езз) тар<з1Пщ, кесогд, 1езз<з1ггпу» т2; Пользуйтесь той версией, которую позволяет реализация.
В конце концов реализации позволят все. Ранние реализации С++ предоставляли 1з1гз1геат и оз1гз1геат, определенные в <з1гзЬ еат.Ь>, а не 1з1г1пяз1геат и оз1г1пдз1егат, определяемые в <зз1геат>. Потоки з1гз1геат работали прямо с сЬагп (см. 9 21.10[2б1). Потоки в реализациях С н-, предшествовавших стандарту, не параметризовались. В частности, шаблоны с префиксом Ьаз1с являются новыми для стандарта, а класс Ьаис юз обычно назывался соз. Довольно любопытно, что 1оз1а1е обычно назывался со з1а1е. 899 Б.З.
Старые реализации С++ Б.З.З. Пространства имен Если ваша реализация не поддерживает пространств имен, для выражения логической структуры программы пользуйтесь исходными файлами (глава 9). Лналогично, для выражения интерфейсов, которые вы предоставляете для реализаций, илп которые являзотся общими с С, пользуйтесь заголовочными файлами. В отсутствие пространств имен, чтобы компенсировать недостаток в неименованных пространствах имен, пользуйтесь к1а11с. Также пользуйтесь идентифзлцирующими префиксами перед глобальными именами, чтобы отличать ва~пи имена от имен из других частей кода. Например; // для использования в реализациях, предшествовавших пространствам имен с1акк Ьк к1ппд ( /' ... '/ й // строка Бьерна 1урес(е1 1п1 Ьк Ьоо1; //логический тип бьерна с1акк1обп кгсгпа, // строка Джона епитуодп Ьоо1((оЬп /а1ке,1одл Гсие~з //логинескш(типДжона Будьте осторожны при выборе префикса.
Существующие библиотеки С и С++ пере- полнены такого рода префиксами. Б.3.4. Ошибки распределения памяти В С.н-до появления обработки исключений оператор пезо возвращал О, когдавыделениепамяти не удавалось. В стандарте С++ пеш по умолчанию генерирует исключение бааз аДос. Какправило,лучшестрелозтьсяксходствусостандартом.
Вданномслучаезтоозначает, что следует изьсенить програмгиу так, чтобы перехватывать Ьас( а/(ос, а не проверять на О. В обоих случаях при исчерпании памяти сделать что-либо, кроме выдачи сообщения об ошибке, не так-то просто в большинстве систем.
Однако, когда преобразование программы от проверки на О к перехватыванию Ьас1 а11ос, нереалистично, вы можете в некоторых случаях изменить программу, чтобы вернуться к поведенизо, соответствующему старым реализациям. Если не задан обработчик пеш ЬапЖег, использование распределителя по1Ьгош приведет к возвращению О в случае неудачного распределения: Х' р1 = пеш Х; //возбуждает Ьад адос. если нет паняти Х" р2= пет (погдсот(Х; // возвращает О, если нет памяти Б.3.5. Шаблоны Стандарт вводит новые средства для работы с шаблонами и вносит ясность в правила работы с некоторыми старыми средствами.
Если ваша реализация не поддерживает частичную специализацию, пользуйтесь отдельным именем для шаблона, который иначе был бы специализацией. Например: 1етр1а1е <с1акк 7» с1акк рдк1: рниа1е1гк1<ио(д*> ( //должно бьыо бн бьсть 11к1<Г> //- )' Если ваша реализация не поддерживает шаблоны членов, некоторые методы станут недоступны.
В частности, шаблоны членов позволяют программисту задавать конструиро- 900 Приложение Б. Совместимость ванне и преобразование с гибкостью, недостижимой без них. Иногда в качестве альтернативы можно рассмотреть введение функции-не-члена, которая конструирует объект: !етр(а1е <с(азз Т с(аззХ( //... гетр(а(е< с1азз А> Х (сопз1 АГ> а), При отсутствии шаблонов-членов, мы должны ограничить себя определенными типами: 1етр!а(е<с(азз Т с1аззХ( //- Х(сопя! АИ а); Х (сопз1А2«а); Большинство ранних реализаций генерировали определения для всех функций-членов, определенных внутри шаблона класса, когда шаблон инстанцировался, Это могло приводить к ошибкам в неиспользуемь!х функциях-членах (з В.13.9.1).
Решение заключается в том, чтобы разместить определение функций-членов после объявления класса. Например, вместо: гетр(а(е<с(азз Т> с(аяз Соп1а(пег( //... рибйс. ооЫ зог1 () ( /" используем < */) // определение внутри класса с(азз 6(оЬ ( /' для 0(оЬ нет < */); СоМаспег<6(оЬ> за; // некоторые реализации, предшествовавшие стандарту, // питаюпия определить Соп(а!пе~~б(оЬ>пяог(~) используйте (етр(а1е<с(азя Т с(азя Соп1ашег( //- риЫ(с: со Ы заг( () ); 1етр(а(е<с(азз Т>иоЫСоп1а!пег<Т':гзог1()(/'используем<'/) //определение вне класса с1азз 61оЬ ( /*для 6(оЬ нет < */), Соп(ашег<6(оЬ> срд //проблем не возникает, пока не будет виэвина су.яод Ранние реализации С++ не понимают членов, определенных в классе позже.
Например; 1етр(а1е -с1азя Т> с!азз ) ес1ос( риЬ(!с: ТЬ орега1огЦ )з(ее 1() ( ге1игп о(!) ) //о объявлена ни>се //. рггоа1е Т о; //не нийдено! з(ге 1зг, В таких случаях или упорядочите объявления членов, чтобы избежать проблем, или расположите определение функций-членов после объявления класса. 901 Б.З. Старые реализации С++ Некоторые реализации С++, предшествовавшие стандарту, не допускают для шаблона аргументов по умолчанию (9 13.4.1). В этом случае каждый параметр шаблона нужно задать как явный аргумент. Например: гетр!а!с<с!авв Т, с!аввФЛ= (евв<Т > с!авв тар ( //..
тор<в!г!пусл! т; //увы: аргументы шаблона по улгол«анаю нереализованы тир<в!ггпу !пг, !евв<гп!» т2; // пойдем в облод: сделаем аргумент явным Б.3.6. Инициализаторы 1ог-инструкции Рассмотрим следующий код: ооЩ(вес!ос<сбег й о, !а!т) ( Ког (гп! 1=0; г<о.в!ее () 66 !<=т; «-+!) сои! «о[!]; К (1==т) ( // ошибка: обращение к ! после]ог //- ) ) Такой код обычно работал, потому что в изначальном определении С++ область ви- димости контролируемых переменных распространялась до конца области видимос- ти, в которую входила~ос-инструкция.
Если вы нашли такой код, просто объявтгте контролируемую переменную перед /ог-инструкцией: с ос! (2 (пес!ос<с(гаг>6 о, т! т) ( !и! «=О; уог (; !<о.в!зе () 68, !<=т; «-»г] сои! . о[г); //г понадооитсл после цикла ф' (г==т) ( //," ) Б.4. Советы [1] Для изучения С++ используйте самую последнюю и полную пз доступных вам реализаций стандартного С»»; 6 Б.З. [2] Общее подмножество С и С.н- яе есть лучшее для изучения начальное подмножество; 6 1.6., 6 Б.З. [3] При создании кода помните: не каждая реализапия С++ полностью обновлена. До того, как использовать новое средство в промышленном коде, попробуйте его в небольшой программе для проверки соответствия стандарту и производительности реализации, ко. торую вы планируете использовать.
Для примера см. 6 85[6-7], 6 16.5[10], 6 Б.5[7]. [4] Избегайте «неодобряемых» возможностей, тина глобальных статических переменных. Избегайте приведения типов в стиле С; 6 6.2.7, 6 Б.2.3. (5] Неявный т!был выкинут,пажмуяшюопределяйте пиюишойг функции,переменной,сопя ипрс з Б22. [6] Прн преобразовании программы с С на С++ сначала убедитесь,что последовательно используются объявления функций (прототипы) и стандартные заголовочные файлы; 6 Б.2.2. [7] Прн преобразовании программы с С на С+ ' переименуйте переменные С, которые совпадают с ключевымн слонами С++; 6 Б.2,2.
Приложение Б. Совместимость 902 [8] При преобразовании программы с С на С-.+ приводите результат, возвращаемый та!!ос () к соответствующему типу, плц замените все вызовы таПос () на иев; 9 Б.2.2. [9] Прц преобразовании та!!ос () и [гее () к иев и г(е1е1е подумайте об использовании иес1ог, рияд Ьаей () и геяегве (), вместо геаяос (); 9 3.8, 9 16.3.5. [10] При преобразовании программы с С на С+ + помните, что нет неявного преобразования от типа Ы1 к перечислениям. Прн необходимости используйте явное преобразование типов; 6 4.8. [11] Средства пз пространства имен яЫ определяются в заголовке без суффикса (т. е.
яЫ" сои! объявлена в <1оя1геат>). Старые реализации содержат средства стандартной библиотеки в глобальном пространстве имен, объявленные в заголовочных файлах с суффиксом . Ь (т, е, ссои! объявлена в <1оя1геат Ь>); 6 9.2.2, 6 БВ.1, [12] В старом коде проверки на равенство 0 результата, возвращаемого иев, дол>к>>ы быть заменены ца перехват исключения Ьат( а1!ос или на использование пети (иояйгов); 6 Б.3.4.
[13] Если ваша реалнзапия не поддерж>гвает аргументы шаблонов по умолчанию, использунте аргу>шиты явно. Часто 1урег!еу" может быть использовано для предотвращения повторения аргументов шаблона (аналогично тому, как 1урег(е~ я1ггла позволяет вам не использовать Ьая1с я(г1ла< сйаг, айаг 1га11я<сйаг», а!1оса1ог<сйаг >); 6 Б.3.5. [14] Используйте <яяг1иц для доступа к яЫс<я1г)иа> (<яяг1иа.й' содержит функции для строк в стиле С); 6 9.2.2, 6 Б.3.1. [15] Для каждого стандартного заголовочного файла языка С <Х.Ь>, который помещает имена в глобальное пространство имен, заголовочиыи файл <сХ> помещает имена в пространство имен яЫ; 6 Б.З 1. [16] Многие системы содержат заголовочный файл '81г1ла.й', определяющий строковый тип.
Отметим, что такие строки отличаются от типа я1г(иа из стандартной библиотеки. [17] Предпочитайте стандартные средства нестандартным; 9 20.1, 9Б.З, В.2. [18] Используйте ех1егл "С" при обьявлении С-функции; 9 9.2.4. Б.5. Упражнения 1. ('2.5) Возьмите программу на С и преобразуйте ее в программу на С++.