Using namespace
Директива_using_namespace импортирует типы, содержащиеся в пространстве имен, в непосредственно вмещающую единицу компиляции или тело пространства имен, что позволяет использовать идентификатор каждого типа без уточнения. директива_using_namespace: Внутри объявлений членов в единице компиляции или теле пространства имен, содержащем директиву_using_namespace, на типы в данном пространстве имен можно ссылаться непосредственно. Пример: namespace N1.N2 namespace N3 class B: A {} В данном примере внутри объявлений членов в пространстве имен N3 члены типа N1.N2 доступны непосредственно, и таким образом класс N3.B является производным от класса N1.N2.A. Директива_using_namespace импортирует типы, содержащиеся в данном пространстве имен, но не импортирует вложенные пространства имен. В этом примере namespace N1.N2 namespace N3 class B: N2.A {} // Error, N2 unknown директива_using_namespace импортирует типы, содержащиеся в N1, но не пространства имен, вложенные в N1. Таким образом, ссылка на N2.A в объявлении B приводит к ошибке времени компиляции, так как в области нет членов с именем N2. В отличие от директивы_using_alias, директива_using_namespace может импортировать типы, идентификаторы которых уже определены внутри вмещающей единицы компиляции или тела пространства имен. В действительности, имена, импортированные директивой_using_namespace, скрыты членами с тем же именем во вмещающей единице компиляции или теле пространства имен. Например: namespace N1.N2 class B {} namespace N3 class A {} В данном случае внутри объявлений членов в пространстве имен N3, A ссылается на N3.A, а не на N1.N2.A. Если более одного пространства имен, импортированных директивами_using_namespace в одну и ту же единицу компиляции или тело пространства имен, содержат типы с одинаковым именем, ссылки на эти типы считаются неоднозначными. В этом примере namespace N1 namespace N2 namespace N3 using N2; class B: A {} // Error, A is ambiguous N1 и N2 содержат член A, а поскольку N3 импортирует оба, ссылка на A в N3 дает ошибку времени компиляции. В этой ситуации можно разрешить конфликт либо квалифицируя ссылки на A, либо введя директиву_using_alias, выбирающую отдельный A. Например: namespace N3 using N2; using A = N1.A; class B: A {} // A means N1.A Как и директива_using_alias, директива_using_namespace не размещает новые члены в базовой области объявлений единицы компиляции или пространства имен, а влияет только на единицу компиляции или тело пространства имен, в котором находится. Имя_пространства_имен;, на которое ссылается директива_using_namespace, разрешается таким же образом, как имя_пространства_имен_или_типа;, на которое ссылается директива_using_alias. Таким образом, директивы_using_namespace в одной и той же единице компиляции или теле пространства имен не влияют друг на друга и могут быть записаны в любом порядке. 9.5 Члены пространства имен Объявление_члена_пространства_имен является либо объявлением_пространства_имен (§9.2), либо объявлением_типа (§9.6). объявления_членов_пространства_имен: объявление_члена_пространства_имен: В единице компиляции или в теле пространства имен могут содержаться объявления_членов_пространства_имен;, и эти объявления размещают новые члены в базовой области объявлений содержащей единицы компиляции или тела пространства имен. 9.6 Объявления типов; Объявление_типа является объявлением_класса (§10.1), объявлением_структуры (§11.1), объявлением_интерфейса (§13.1), объявлением_перечисляемого_типа (§14.1) или объявлением_делегата (§15.1). объявление_типа: Объявление_типа; может быть объявлением верхнего уровня в единице компиляции или объявлением члена внутри пространства имен, класса или структуры. Если объявление типа для типа T является объявлением верхнего уровня в единице компиляции, полное имя вновь объявленного типа просто T. Если объявление типа для типа T находится внутри пространства имен, класса или структуры, то полное имя вновь объявленного типа N.T, где N является полным именем содержащего пространства имен, класса или структуры. Тип, объявленный внутри класса или структуры, называется вложенным типом (§10.3.8). Разрешенные модификаторы доступа и доступ по умолчанию для объявления типа зависит от контекста, в котором имеет место объявление (§3.5.1): · типы, объявленные в единицах компиляции или в пространствах имен, могут иметь доступ public или internal. Доступ по умолчанию internal; · типы, объявленные в классах, могут иметь доступ public, protected internal, protected, internal или private. Доступ по умолчанию private; · типы, объявленные в структурах, могут иметь доступ public, internal или private. Доступ по умолчанию private. 9.7 Квалификаторы псевдонима пространства имен Квалификатор псевдонима пространства имен:: дает возможность гарантировать, что на поиск имени типа не будет влиять введение новых типов и членов. Квалификатор псевдонима пространства имен всегда стоит между двумя идентификаторами, которые называют левым и правым. В отличие от регулярного квалификатора., поиск левого идентификатора квалификатора:: выполняется только как поиск псевдонима extern или using. Уточненный_член_псевдонима; определяется следующим образом: уточненный_член_псевдонима: Уточненный_член_псевдонима можно использовать как имя_пространства_имен_или_типа (§3.8) или как левый операнд доступа_к_члену (§7.6.4). Уточненный_член_псевдонима может принимать одну из двух форм: · N::I<A1,..., AK>, где N и I представляют идентификаторы, а <A1,..., AK> — список аргументов типа. (K всегда по меньшей мере единица); · N::I, где N и I представляют идентификаторы (в этом случае K считается равным нулю). При использовании этой нотации значение уточненного_члена_псевдонима; определяется следующим образом: · если N является идентификатором global, то поиск I ведется в глобальном пространстве имен: o если в глобальном пространстве имен содержится пространство имен с именем I, а K равно нулю, то уточненный_член_псевдонима ссылается на это пространство имен; o иначе, если в глобальном пространстве имен содержится неуниверсальный тип с именем I, а K равно нулю, то уточненный_член_псевдонима; ссылается на этот тип; o иначе, если в глобальном пространстве имен содержится тип с именем I, у которого имеется K параметров типа, то уточненный_член_псевдонима; ссылается на этот тип, сформированный с данными аргументами типа; o иначе уточненный_член_псевдонима; не определен и выдается ошибка времени компиляции. · иначе, начиная с объявления пространства имен (§9.2), непосредственно содержащего уточненный_член_псевдонима; (если имеется), далее для каждого вмещающего объявления пространства имен (если имеются), и заканчивая единицей компиляции, содержащей уточненный_член_псевдонима;, оцениваются следующие шаги, пока не будет обнаружена сущность: o если в объявлении пространства имен или в единице компиляции содержится директива_using_alias, связывающая N с типом, то уточненный_член_псевдонима; не определен и выдается ошибка времени компиляции; o иначе, если в объявлении пространства имен или в единице компиляции содержится директива_extern_alias или директива_using_alias, связывающая N с пространством имен, то: · если в пространстве имен, связанном с N, содержится пространство имен с именем I, а K равно нулю, то уточненный_член_псевдонима ссылается на это пространство имен; · иначе, если в пространстве имен, связанном с N, содержится неуниверсальный тип с именем I, а K равно нулю, то уточненный_член_псевдонима ссылается на этот тип; · иначе, если в пространстве имен, связанном с N, содержится тип с именем I, у которого имеется K параметров типа, то уточненный_член_псевдонима; ссылается на этот тип, сформированный с данными аргументами типа; · иначе уточненный_член_псевдонима; не определен и выдается ошибка времени компиляции. · иначе уточненный_член_псевдонима; не определен и выдается ошибка времени компиляции. Обратите внимание, что использование квалификатора псевдонима пространства имен с псевдонимом, ссылающимся на тип, вызывает ошибку времени компиляции. Кроме того, если N является идентификатором global, то поиск выполняется в глобальном пространстве имен, даже если существует псевдоним using, связывающий global с типом или пространством имен. 9.7.1 Уникальность псевдонимов В каждой единице компиляции и теле пространства имен имеется отдельная область объявлений для псевдонимов extern и using. Так, хотя имя псевдонима extern или псевдонима using должно быть уникальным внутри набора псевдонимов extern и псевдонимов using, объявленных в непосредственно содержащей единице компиляции или теле пространства имен, псевдоним может иметь то же имя, что и тип или пространство имен, если он используется только с квалификатором. В этом примере namespace N public class B {} namespace N class X A::Stream s2; // Ok у имени A два возможных значения в теле второго пространства имен, так как и класс A, и псевдоним A находятся в области. Поэтому использование A в уточненном имени A.Stream неоднозначно и приводит к ошибке времени компиляции. Однако использование A с квалификатором:: не является ошибкой, так как поиск A ведется только как псевдонима пространства имен.
10. Классы; Класс — это структура данных, которая может содержать члены данных (константы и поля), члены функций (методы, свойства, события, индексаторы, операторы, конструкторы экземпляров, деструкторы и статические конструкторы) и вложенные типы. Типы классов поддерживают наследование — механизм, в котором производный класс может расширять и сужать базовый класс. 10.1 Объявления классов; Объявлением_класса является объявление_типа (§9.6), которое объявляет новый класс. объявление_класса: Объявление_класса состоит из необязательного набора атрибутов (§17), затем следует необязательный набор модификаторов_класса (§10.1.1), необязательный модификатор partial, ключевое слово class и идентификатор;, именующий класс, затем следует необязательный список_параметров_типа (§10.1.3), необязательная спецификация базы_класса (§10.1.4), необязательный набор предложений_ограничений_параметров_типа (§10.1.5), тело_класса (§10.1.6) и необязательная точка с запятой. Объявление класса не предоставляет предложения_ограничений_параметров_типа;, если не предоставляется список_параметров_типа;. Объявление класса, предоставляющее список_параметров_типа;, является объявлением универсального класса. Кроме того, любой класс, вложенный в объявление универсального класса или в объявление универсальной структуры, сам является объявлением универсального класса, так как параметры типа для содержащего типа должны быть указаны для создания сформированного типа. 10.1.1 Модификаторы классов; Объявление_класса может включать последовательность модификаторов класса. модификаторы_класса: модификатор_класса: Появление в объявлении класса одного и того же модификатора несколько раз является ошибкой времени компилирования. Модификатор new допускается во вложенных классах. Он определяет скрытие классом унаследованного члена
|