Г. Шилдт - С#4.0 Полное руководство (1160795), страница 99
Текст из файла (страница 99)
с1аяя Соиптир ( тпг ча1; тпг гагдег; риЫ1с Тпт Тагдет ( дег( гегигп тагдет(, ) риы1с соипгдр(зпг и) ( тагдет = и; ча1 = О; ) риЫ1с чо10 Ваяет(1пг и) гагдет = и; ча1 = 0; ) риЪ1тс 1пт Соипт() ( 1Г(ча1 < тагдег) гегигп ча1т+т е1яе гетигп тагдет( ) ) с1аяв МОРеюо5 ( втат1с чо10 Мати() ( СоиптОомп сс) = пем Соиптсомп(10)) Соиптир си = пем Соиптдр(В); П(ава 16.
Пространства имен, препроцессор и сборки 523 ьпс 1; оо ( сс.сопля(); Сспво1е,иг1ге(1 ) ий11е (1 > О): Сопяс1е.иг1сеььпе(); со ( = сп.Сопля(); Сспяо1е.игьге(1 т " ")т ) нп11е(1 < си.тагоег)) ) ) Вот к какому результату приводит выполнение этой программы. 10987б543210 01234 5б78 Обратите также внимание на то, что директива пягпч Соппсег," делает видимым все содержимое пространства имен Спонге г. Это дает возможность обращаться к классам Сопл СРохп и Сон пг()р непосредственно, т.е.
без дополнительного указания пространства имен. При этом разделение пространства имен Сопл гег на две части не имеет никакого значения. Вложенные пространства имен Одно пространство имен может быть вложено в другое. В качестве примера рассмотрим следующую программу. // Вложенные пространства имен. пвгпс Яувсепт паыеврасе ХЯ1 ( с1аяя С1аявй ( рцп11с С1аяяй() ( Сопво1е.игьсевгпе("Конструирование класса С1вяяй")т ) ) паиеврасе НЯ2 ( // вложенное пространство имен с1аяв С1авяВ рпо11с С1аяяВ() ( Сопяо1е.иггге11пе("Конструирование класса С1вяяВ") ) с1авя Хеягеснзоеыо ( Вса11С лоте МВ1П() ( 524 часть (.
язык С() Няг.ога А а = п Ня(.огаввд() МЯ2.С1азаВ Ь = лен МЯ2.С1аввв(); // Неверно!!! Пространство НЯ2 невидимо НЯ(.нвг.егаввВ Ь = пе НЯ(.нзг.сгаваВ()г О вер ) ) Выполнение этой программы дает следующий результат. Конструирование класса С1аваА Конструирование класса С1аввВ В этой программе пространство имен Няг вложено в пространство имен НЯ1. Поэтому для обращения к классу с1авяв необходимо дополнительно указать пространства имен НЯ 1 и НЯ 2. Указания одного лишь пространства имен ХЯ2 для этого недостаточно. Как следует из приведенного выше примера, пространства имен дополнительно указываются через точку. Следовательно, для обращения к классу С1ая БВ в методе Маги () необходимо указать его полное имя — МБ1.
МЯ2. С1аввВ. Пространства имен могут быть вложенными больше, чем на два уровня. В этом случае член вложенного пространства имен должен быть дополнительно определен с помощью всех охватывающих пространств имен. Вложенные пространства имен можно указать в одном операторе паиеврасе, разделив их точкой. Например, вложенные пространства имен паиевраое опоетня ( паиезрасе гппетМЯ ( ) ) могут быть указаны следующим образом.
паиеврасе Оотетня.1ппегия ( ) Глобальное пространство имен Если в программе не объявлено пространство имен, то по умолчанию используется глобальное пространство имен. Именно поэтому в примерах программ, представленных в предыдущих главах книги, не нужно было обращаться для этой цели к ключевому слову папгеярасе. Глобальное пространство удобно для коротких программ, как в примерах из этой книги, но в большинстве случаев реальный код содержится в объявляемом пространстве имен.
Главная причина инкапсуляции кода в объявляемом пространстве имен — предотвращение конфликтов имен. Пространства имен служат дополнительным средством, помогающим улучшить организацию программ и приспособить их к работе в сложной среде с современной сетевой структурой. Применение описателй псевдонима пространства имен Пространства имен помогают предотвратить конфликты имен, но не устранить их полностью. Такой конфликт может, в частности, произойти, когда одно и то же имя Глава 16. Пространства имен, препроцессор и сборки 525 объявляется в двух разных пространствах имен и затем предпринимается попытка сделать видимыми оба пространства.
Допустим, что два пространства имен содержат класс МуС1аяя. Если попытаться сделать видимыми оба пространства имен с помощью директикця1по, то имя мус1ая я из первого пространства вступит в конфликт с именем МуС1аяя из второго пространства, обусловив появление ошибки неоднозначности. В таком случае для указания предполагаемого пространства имен явным образом можно воспользоваться описагнелем псевдонима иросвранс)нва имен г м Ниже приведена общая форма оперртора::. псевдоним пространства имен::идентификатор Здесь псевдоним пространства имен обозначает конкретное имя псевдонима пространства имен, а идентификатор — имя члена этого пространства.
Для того чтобы стало понятнее назначение описателя псевдонима пространства имен, рассмотрим следующий пример программы, в которой создаются два пространства имен, Соцпг ее и АпоСЬе хСоппсег, и в обоих пространствах объявляется класс Сон п ЬОонп. Затем оба пространства имен становятся видимыми с помощью директив пялим. И наконец, в методе Ма1п () предпринимается попытка получить экземпляр объекта типа СоцпЬРоып.
О Продемонстрировать необходимость описателя пя1пй Буягещг // Использовать оба пространства имен Сопппег и Апосйегсоппгег. пятпс Сопппег; иятпй Апоспегсоопсег; Объявить пространство имен для счетчиков. пащеярасе Сопппег ) // Простой аычитающий счетчик. с1аяя Соппгоочп ) фпс ча1; риЬ11с Соипгоонп)1пг и) ( ча' = и; Объявить еще одно пространство имен для счетчиков. пащеярасе Апоспегсопппег ) // Объявить еще один класс Соппгпонп, принадлежащий пространству имен Апоппегсопппег.
с1аяя Соппгпонп ) тпс ча1; рпЬ11с Соппсооип)лпг и) ) ча1 = и; О 526 Часть (. Язык Сй с1аяя ИьуА11аяоиа11тьет ( ягат1с чо1б Ма1п() ( 1пс 1? // Следующая строка, пс существу, неоднозначна! Неясно, делается ли в ней ссылка на класс Соппппонп из пространства имен Сопптег или АпотйетСопптет? Соппгсонп сб1 = пен Сочппоснп(10)? // Ошибка! ( ! // ) ) Если попытаться скомпилировать эту программу, то будет получено сообщение об ошибке, уведомляющее о неоднозначности в следующей строке кода из метода Мата () .
Сспптоснп сб1 = пен Сппптпснп(10)? // Ошибка! ! ! Причина подобной неоднозначности заключается в том, что в обоих просграйствах имен, Сопптег и АпосйехСоппсег, объявлен класс Соппспоып и оба пространства сделаны видимыми. Поэтому неясно, к какому именно варианту класса Соппгпоып следует отнести приведенное выше объявление. Для,устранения подобного рода недоразумений и предназначен описатель::. Для того чтобы воспользоваться описателем::, необходимо сначала определить псевдоним для пространства имен, которое требуется описать, а затем дополнить описание неоднозначного элемента этим псевдонимом.
Ниже приведен вариант предыдущего примера программы, в котором устраняется упомянутая выше неоднознач-, ность. // Продемонстрировать применение описателя пя1пс Буясеш? пя1пс Соипгег? пятпд Апстьехсспппет? // Присвоить классу Ссппгег псевдоним Сгт. пятпд сгт = соппсег? Объявить пространство имен для счетчиков. пашеярясе Сочпгех ( // Простой яычитаюший счетчик.
с1аяя Сочптпснп ( 1пп ча1; риЬ11с Ссппппснп(тпт и) ( ча1 = и; Глава 16. Пространства имен, препроцессор и сборки 527 Объявить еще одно пространство имен для счетчиков. пашеярасе Лпоткегсоопгег ( Объявить еще один класс Соопгпонп, принадлежащий пространству имен Лпопвегсооппег. с1аяя Соипгпонп ( гпс ча1; роЬ11с Соепгоонп(гпг и) ( на1 = пг ) с1аав Л11аяфоа11Г1егпешо ясаггс чола На1п() ( Здесь оператор :: разрешает конфликт, предписывая компилятору использовать класс Сооптоонп из пространства имен Сочпгег. Сгг::Соопгоонп сб1 = пеи Сгг::Соипгбонп(10); В этом варианте программы для класса Соппбег сначала указывается псевдоним Сбг в следующей строке кода.
пятно Сгг = Соипгег; А затем этот псевдоним используется в методе ма1п () для дополнительного описания класса Сопл СРоип, как показано ниже. Сгг::Соопббонп сб1 = пен Сгг::Соопгоонп(10) Описатель:: устраняет неоднозначность, поскольку он явно указывает на то, что следует обратиться к классу Сопл СРомп из пространства С С г, а фактически — Сапог ел. Именно это и делает теперь программу пригодной для компиляции.
Описатель:: можно также использовать вместе с предопределенным идентификатором с1ОЬа1 для ссылки на глобальное пространство имен. Например, в приведенной ниже программе класс соппсРоып объявляется как в пространстве имен соппсег, так и в глобальном пространстве имен. А для доступа к варианту класса соппсРонд в глобальном пространстве имен служит предопределенный псевдоним о1ОЬа1. использовать псевдоним глобального пространства имен. оя1пд Зуясеш; Присвоить классу соипсег псевдоним ссг. оя1по сгг = соопсегг // Объявить пространство имен для счетчиков.
523 Часть!. Язык С№ пашеврасе Соппсег ( Простой вычитаюший счетчик. с1аяя Соппгоонп ( 1пс ча1; рпЬ11с Соппгоонп(1по и) ( ча1 = и; ) Объявить еще один класс Соппсбонп, принадлежащий глобальному пространству имен. с1аяя Соппгбонп ( 1пс ча1) роЬ)..(с Сочп(.пони (1п(. и) ( ча1 = и; ) с1аяв 61оЬа1А11аяооа1111егоешо ( ясагьс чо10 Ма1п Ы // Здесь описатель :: предписывает компилятору использовать класс Соппооонп из пространства имен Соопгет. Спг::Соопсоонп сб1 = пен Сгг::Соппооонп(10); // Далее создать объект класса Соопгоонп из // глобального пространства имен.
01оЬа1::соопсоонп сб2 = пен 01оЬа1::соппсбонп(10)г Обратите внимание на то, что идентификатор д1оЬа1 служит для доступа к классу соппс осип из используемого по умолчанию пространства имен. 01оЬа1::СоспСРонп сб2 = пен 01оЬа1::Соопгоонп(10) Этот подход можно распространить на любую ситуацию, в которой требуется указывать используемое по умолчанию пространство имен. И последнее: описатель псевдонима пространства имен можно применять вместе с псевдонимами типа ехс его, как будет показано в главе 20. Препроцессор В С(( определен ряд директив препроцессора, оказывающих влияние на интерпретацию исходного кода программы компилятором. Эти директивы определяют поря- Глава 16. Пространства имен, препроцвссвр я сборки 529 док интерпретации текста программы перед ее трансляцией в объектный код в том исходном файле, где они появляются.