Б. Страуструп - Дизайн и Эволюция C++. 2006 (1160775), страница 100
Текст из файла (страница 100)
В моем первоначальном проекте у цв1пя-директив был более простой и лаконичный синтаксис: пвтпд А; // означает "нвгпд папеврасе А;" Это привело к путанице: вместо пв1пя-директив использовали ив)пя-объявления и наоборот. С введением более явного синтаксиса неразбериха исчезла. Также упростился синтаксический анализатор. Я предвидел, что пользователи захотят избегать длинных имен. Поэтому в первоначальном проекте в одном псйпй-объявлении было разрешено указывать имена нескольких членов: ивгпд Х::(Г,д,П); Однако зто неудачно, равно как и все рассмотренные нами альтернативы.
Точнее, каждая из обсуждавшихся альтернатив хоть кем-то была признана неудачной. Получив некоторый опыт работы с пространствами имен, я понял, что потребность в таких списках возникает куда реже, чем ожидалось. Кроме того, при чтении кода я обычно не обращал внимания на такие списки, так как они слишком похожи на объявления функций. Поэтому вместо них я стал употреблять повторные пв)пй-объявления: ивтпд х::Г; ивхпд х::д; ыв(пд х::Ь| Ув) пя-объявление вводит синоним для некоторого имени в локальную область действия.
Вместо этого мы можем сделать доступными без квалификации все имена из некоторой библиотеки с помощью цв(пя-директивы: в~яи~из! Пространства имен Вот почему в окончательном варианте для задания списка имен в пяпй-объявлении не осталось специального синтаксиса. Пространства имен — зто пример средства, которое после экспериментирования значительно упростилось. Реализовать его также оказалось легко, поскольку пространства имен прекрасно укладываются в общую концепцию классов и областей действия С++.
17.4Л. Мнения по поводу пространств имен После неоднократных попыток согласовать противоречивые взгляды на то, что именно требуется от пространств имен в больших программах, выкристаллизовались три способа доступа к именам. Одни пользователи настаивали, что надежную и поддающуюся сопровождению программу можно построить только в том случае, если каждое применение нелокального имени будет явно квалифицировано.
Естественно, что сторонники данной точки зрения весьма сомневались в полезности пгйпй-объявлений и уж тем более пз1пя-директив. Другие осуждают явную квалификацию за излишнюю многословность, которая якобы затрудняет изменение кода, ограничивает гибкость и лишает практического смысла переход к использованию пространств имен. Разумеется, такие люди выступают за паня-директивы и иные механизмы, позволяющие заменять длинные квалифицированные имена короткими синонимами. Я с сочувствием отношусь к смягченным вариантам той и другой точек зре, ния, поэтому при работе с пространствами имен допустим любой стиль. Как обычно, ничто не мешает конкретной организации составить руководство по стилю программирования, в котором будут описаны корпоративные требования.
Но заставлять всех программистов им следовать, вводя некоторое языковое правило, было бы неразумно. Многие не без оснований опасаются исчезновения обычных неквалифицированных имен. Речь идет о привязке имени не к тому объекту или функции, которые имел в виду программист. Каждый программист на С хотя бы однажды сталкивался с данным явлением. Явная квалификация практически снимает эту проблему. К тому же ряду относится опасение, что будет трудно найти объявление имени идогадатьсл о смысле содержащего его выражения. Явная квалификация содержит столь очевидные указания, что часто и искать-то объявление не нужно: сочетания имени библиотеки с именем функции бывает вполне достаточным для понимания смысла выражения.
Поэтому необычные или нечасто используемые нелокальные имена лучше квалифицировать явно; код от этого только станет яснее. С другой стороны, явная квалификация имен, о которых все знают (или должны знать), и тех, которые часто используются, может быстро надоесть. Например, запись зМто:: рг~псй, таси:: зс1гс, тозсгеав:: соус вряд ли хоть чем-то поможет человеку, знакомому с С++, а никому не нужная громоздкость становится источником ошибок.
Это сильный аргумент в пользу пз1пя-объявлений и псйпйдиректив. При этом пз1пя-обьявления — более избирательный и потому гораздо менее опасный механизм. \1сйпй-директива изтпд пазезрасе х; ИИИИИИИШ Решение: пространства имен пв1ПП Х::г; пв1пп х::П~ ааспб х::'и; Но иногда возможность получить доступ к каждому имени из пространства имен, не перечисляя их все, с автоматическим изменением множества доступных имен после модификации определения х — как раз то, что нужно.
17А.2. Внедрение пространств имен Принимая во внимание наличие миллионов строк кода на С++, зависящих от использования глобальных имен и существующих библиотек, я полагал, что самый важный вопрос о пространствах имен — как их внедрить? Неважно, насколько изящно выглядит код, в котором применяются пространства имен, если ни у пользователей, ни у поставщиков библиотек нет пути для перехода к применению нового механизма.
Требовать масштабного переписывания кода — это, конечно, не вариант. Рассмотрим каноническую программу на С, с которой всегда начинают обучение этому языку: ()(пс1ис)а <вго1о.п> 1пг эа1п() ( рг1псг("Не11о, ног1П1п"); ) Эта программа не должна переставать работать. Не нравится мне и предложение считать стандартные библиотеки особым случаем. Я признаю очень важной возможность применения механизма пространств имен к стандартным библиотекам на общих основаниях.
Но комитет по стандартизации не вправе требовать для своих библиотек привилегий, которые не в состоянии предоставить поставщикам других библиотек. Ключом к решению этой задачи являются пз(пд-директивы. Например, файл всЖо . Ь помещается в пространство имен: // вМ(о.'и: папеврасе вго ( // 1пс ргьпс1(сопвс снаг* ...
); // ) пв(пд папеврасе вМ; делает видимым неизвестное множество имен. В частности, сегодня это множе- ство может быть одним, а завтра, после внесения изменений в х, — совершенно другим. Те, кому такой подход не нравится, могут явно указать нужные им имена из х в пз(па-объявлениях: ЮИИИИИ Пространства имен Этим достигается обратная совместимость, а для тех, кто не хочет, чтобы имена были доступны неявно, определяется новый заголовочный файл всс(го: // вгбто: паиеврасе всб ( // Гпг ргтпсГ(сопел спаг* ... ); // ) Те, кому не нравится дублирование объявлений, конечно, просто включат всс(го в определение вЫго.)т: // всЖо.'и: ()тпс1ис)е <вгЖо> ивгпп паиеврасе всд; Думаю, что пгйпй-директивы — это, в первую очередь, инструмент, облегчающий переход к пространствам имен. Большинство программ станут яснее, если при обрашении к именам из внешних пространств будут использоваться явная квалификация и цз1пя-объявления.
Конечно, имена из пространства имен, в котором они определены, не требуют никакой квалификации: г(): // вызывается А::г; квалификация не нужна // В этом отношении пространства имен ведут себя так же, как классы. 77.4З. Псевдонимы пространства имен Если пользователь дает своим пространствам имен короткие имена, возможен конфликт, например: павеврасе А (// короткое имя пространства имен // когда-нибудь обязательно возникнет конфликт // паиеврасе А ( уоЫ г(); уоЫ д() ( уорд А.":2() ( а() ' // ) // вызывается А::о; квалификация не нужна МИИИИИИВ Решение: пространства имен А::Бсггпд в1 = "авог"; А::Ясг1пд в2 = "1(сЗЬ"; Но длинные имена писать утомительно: пашеврасе Ашег1сап Те1ерпопе апо Те1едгарп ( // слишком длинное для // использования в реальном коде // Ашег(сап те1ерпопе апс( те1едгарл::Бгг1пд вз = "авдг"; Ашеггсап те1ерпопе апс( Те1едгарп~:Бгг(пд в4 = '1кзп"/ Эту дилемму можно разрешить, введя короткий псевдоним для длинного имени пространства имен: // использование псевдонима для длинного имени пространства имен пашеврасе Атт = Ашеггсап те1ерпопе апс( те1едгарп; АТТ::Ясг(пд вЗ = авс(Г"; АТТ::Ясг(пд в4 = "1)сЗЬ"; пашеврасе ну Тпгеггасе ( пв(пд пашеврасе Ашег1сап Те1ерпопе апо Те1едгарвш пвгпд му оип::Ягг(пд; ивгпд пашеврасе 01; // разрешить конфликт между определениями 'Б1адв' // из 01 и Ашег1сап Те1ерьопе апс( Те1едгарп куреней Тпс у1адв; // 17.4.4.
Исполыование пространств имен для управления версиями В качестве примера применения пространств имен показывается, как постав~пик библиотеки мог бы воспользоваться ими для решения проблемы несовместимых отличий между разными версиями. Этот прием мне впервые продемонстрировал тандж Венетт (тап1 Веппегг). Вот первая версия ге1еаве1: пашеврасе ге1еаве1 ( // с1авв Х ( 1шр1:гкгер* р; риЬ11с: Такая возможность позволяет пользователю обращаться к библиотеке, не указывая каждый раз ее настоящего имени.