Пространства имен в языке c
namespace (Справочник по C#) namespace (C# Reference)
Ключевое слово namespace используется для объявления области действия, которая содержит набор связанных объектов. The namespace keyword is used to declare a scope that contains a set of related objects. Пространство имен можно использовать для организации элементов кода и для создания глобально уникальных типов. You can use a namespace to organize code elements and to create globally unique types.
Remarks Remarks
В пространстве имен можно объявить ноль или больше следующих типов: Within a namespace, you can declare zero or more of the following types:
другое пространство имен another namespace
Независимо от того, было ли пространство имен объявлено явным образом в исходном файле на языке C#, компилятор добавляет пространство имен по умолчанию. Whether or not you explicitly declare a namespace in a C# source file, the compiler adds a default namespace. Это безымянное пространство имен, иногда называемое глобальным пространством имен, существует в каждом файле. This unnamed namespace, sometimes referred to as the global namespace, is present in every file. Любой идентификатор в глобальном пространстве имен доступен для использования в именованном пространстве имен. Any identifier in the global namespace is available for use in a named namespace.
Пространства имен неявно имеют общий доступ, и это невозможно изменить. Namespaces implicitly have public access and this is not modifiable. Описание модификаторов доступа, которые можно назначить элементам в пространстве имен, см. в разделе Модификаторы доступа. For a discussion of the access modifiers you can assign to elements in a namespace, see Access Modifiers.
Пространство имен можно определить в двух или нескольких объявлениях. It is possible to define a namespace in two or more declarations. Например, в следующем примере два класса определяются в качестве части пространства имен MyCompany : For example, the following example defines two classes as part of the MyCompany namespace:
Пример Example
В следующем примере показано, как можно вызвать статический метод вложенного пространства имен. The following example shows how to call a static method in a nested namespace.
Спецификация языка C# C# language specification
Дополнительные сведения см. в статье Пространства имен в разделе Предварительная спецификация C# 6.0. For more information, see the Namespaces section of the C# language specification.
Использование пространств имен. (Руководство по программированию в C#) Using namespaces (C# Programming Guide)
Доступ к пространствам имен Accessing namespaces
Например, включив строку For example, by including the line:
в начале программы, программист может использовать код At the start of a program, the programmer can use the code:
вместо следующего кода: Instead of:
Псевдонимы пространств имен Namespace aliases
Можно также использовать директиву using для создания псевдонимов пространства имен. You can also use the using directive to create an alias for a namespace. Используйте квалификатор псевдонима пространства имен :: для доступа к членам пространства имен, обозначенного псевдонимом. Use the namespace alias qualifier :: to access the members of the aliased namespace. В следующем примере показано, как создать и использовать псевдоним для пространства имен. The following example shows how to create and use a namespace alias:
Использование пространств имен для управления областью действия Using namespaces to control scope
Полные имена Fully qualified names
Пространства имен и типы имеют уникальные названия, которые описываются полными именами, определяющими их место в логической иерархии. Namespaces and types have unique titles described by fully qualified names that indicate a logical hierarchy. Например, инструкция A.B указывает, что A — это пространство имен или тип, а B — вложенный в него элемент. For example, the statement A.B implies that A is the name of the namespace or type, and B is nested inside it.
В следующем примере показаны вложенные классы и пространства имен. In the following example, there are nested classes and namespaces. Полное имя каждого элемента указано в комментарии рядом с ним. The fully qualified name is indicated as a comment following each entity.
В предыдущем фрагменте кода: In the previous code segment:
Использование :: с псевдонимом, ссылающимся на тип вместо пространства имен, будет ошибкой. It is an error to use :: with an alias that references a type instead of a namespace. Пример: For example:
Если определить псевдоним с именем global, возникнет предупреждение компилятора CS0440. Это связано с тем, что global:: всегда ссылается на глобальное пространство имен, а не на псевдоним. Compiler warning CS0440 is generated if you define an alias named global because global:: always references the global namespace and not an alias. Например, предупреждение возникнет в следующем случае: For example, the following line generates the warning:
Изучаем C++. Часть 8. Библиотеки и пространства имён
Разбираемся, как ускорить работу с кодом в несколько раз, используя готовые решения.
Это восьмая часть из серии статей «Глубокое погружение в C++». В прошлой статье мы узнали, как хранить данные в массивах. Сегодня — ещё интереснее.
Недавно мы говорили о том, что многие функции уже написаны другими разработчиками и помещены в специальные библиотеки. Если такая библиотека входит в состав языка или находится в открытом доступе, то вы можете использовать все её возможности.
Это очень удобно, и многие специально пишут универсальные библиотеки, которые пригодятся в самых разных проектах. Давайте разберёмся с библиотеками подробнее и научимся создавать свои.
Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.
Пространства имён в C++
Пространство имён (англ. namespace) — это группа взаимосвязанных функций, переменных, констант, классов, объектов и других компонентов программы.
С самого начала изучения C++ мы используем команду std: cout, чтобы выводить данные в терминал. На самом деле команда называется просто cout, а std — это пространство имён, в котором она находится.
Пространства имён нужны, чтобы логически связывать части программы. Например, математические функции, физические, бухгалтерские и так далее.
Вот пример создания пространства имён:
Мы объединяем в группу несколько разных команд и избегаем конфликтов имён. Это нужно, когда в какой-то из подключённых вами библиотек уже есть функция, например sum (). По пространству имён программа поймёт, какая именно функция вам нужна.
Если же вы хотите сократить код, то используйте команду using:
В данном случае команда говорит, что вам нужны имена из mynames и std, поэтому никакой ошибки выведено не будет.
Также после using можно указать не целое пространство имён, а только отдельную функцию или переменную:
Файлы заголовков в C++
Пространство имён из примера выше можно перенести в отдельный файл, чтобы потом подключить его к другой программе и избавиться от дополнительного кода в основном файле.
Здесь нет функции main (), потому что этот код — не самостоятельная программа, а библиотека для других программ. Следовательно, точка входа здесь не нужна. Также мы не подключаем iostream, потому что не собираемся ничего выводить, но вы можете добавить в свой заголовок любые другие файлы.
Поместите mylib.h в папку, где находится ваша программа. Затем добавьте в начало кода команду:
Обратите внимание на двойные кавычки вместо угловых скобок: первые используются для локальных заголовков, а вторые — для системных.
Теперь вы можете использовать весь функционал из этой библиотеки:
Вот что будет выведено:
Обратите внимание, что функция pow, как и другие математические функции, существует также и в библиотеке cmath.
Заключение
Библиотеки и пространства имён — это полезные инструменты для каждого разработчика. В интернете есть готовые решения для любых задач, поэтому многие работодатели ищут специалистов, которые разбираются в определённой библиотеке.
Если вы часто работаете над однотипными проектами, можете написать для себя библиотеку и подключать её во все проекты, чтобы ускорить работу. Однако новичкам стоит стараться писать код каждый раз заново — так вы сможете его постоянно переосмысливать и замечать то, чего раньше не замечали.
Если вы хотите освоить С++, то можете пройти наш курс. В нём все аспекты языка разбираются детально и на практике, а в конце каждого задания вы получаете обратную связь от преподавателей.
Профессия
Разработчик на C++ с нуля
Вы пройдёте полный курс по С++ и прикладной курс по Unreal Engine 4. Вы научитесь работать с многопоточностью, использовать инструменты и средства разработки: Git, GCC, GDB. Вам будет проще найти работу программиста в геймдеве.
Урок №53. Пространства имен
Обновл. 24 Окт 2020 |
Этот урок является продолжением урока №24.
Конфликт имен
Конфликт имен возникает, когда два одинаковых идентификатора находятся в одной области видимости, и компилятор не может понять, какой из этих двух следует использовать в конкретной ситуации. Компилятор или линкер выдаст ошибку, так как у них недостаточно информации, чтобы решить эту неоднозначность. Как только программы увеличиваются в объемах, количество идентификаторов также увеличивается, следовательно, увеличивается и вероятность возникновения конфликтов имен.
Рассмотрим пример такого конфликта. boo.h и doo.h — это заголовочные файлы с функциями, которые выполняют разные вещи, но имеют одинаковые имена и параметры.
Если boo.h и doo.h скомпилировать отдельно, то всё пройдет без инцидентов. Однако, соединив их в одной программе, мы подключим две разные функции, но с одинаковыми именами и параметрами, в одну область видимости (глобальную), а это, в свою очередь, приведет к конфликту имен. В результате, компилятор выдаст ошибку. Для решения подобных проблем и добавили в язык С++ такую концепцию, как пространства имен.
Что такое пространство имен?
Пространство имен определяет область кода, в которой гарантируется уникальность всех идентификаторов. По умолчанию, глобальные переменные и обычные функции определены в глобальном пространстве имен. Например:
Глобальная переменная g_z и функция boo() определены в глобальном пространстве имен.
В примере, приведенном выше, при подключении файлов boo.h и doo.h обе версии doOperation() были включены в глобальное пространство имен, из-за чего, собственно, и произошел конфликт имен.
Чтобы избежать подобных ситуаций, когда два независимых объекта имеют идентификаторы, которые могут конфликтовать друг с другом при совместном использовании, язык C++ позволяет объявлять собственные пространства имен через ключевое слово namespace. Всё, что объявлено внутри пользовательского пространства имен, — принадлежит только этому пространству имен (а не глобальному).
Перепишем заголовочные файлы из вышеприведенного примера, но уже с использованием namespace:
Результатом будет еще одна ошибка:
C:\VCProjects\Test.cpp(15) : error C2065: ‘doOperation’ : undeclared identifier
Случилось так, что когда мы попытались вызвать функцию doOperation(), компилятор заглянул в глобальное пространство имен в поисках определения doOperation(). Однако, поскольку ни одна из наших версий doOperation() не находится в глобальном пространстве имен, компилятор не смог найти определение doOperation() вообще!
Существует два разных способа сообщить компилятору, какую версию doOperation() следует использовать: через оператор разрешения области видимости или с помощью using-стейтментов (о них мы поговорим на следующем уроке).
Доступ к пространству имен через оператор разрешения области видимости (::)
Первый способ указать компилятору искать идентификатор в определенном пространстве имен — это использовать название необходимого пространства имен вместе с оператором разрешения области видимости ( :: ) и требуемым идентификатором.
Например, сообщим компилятору использовать версию doOperation() из пространства имен Boo :
Пространства имен (C++) Namespaces (C++)
В следующем примере показано объявление пространства имен и продемонстрированы три способа доступа к членам пространства имен из кода за его пределами. The following example shows a namespace declaration and three ways that code outside the namespace can accesses their members.
Использование полного имени: Use the fully qualified name:
Чтобы добавить в область видимости один идентификатор, используйте объявление using: Use a using declaration to bring one identifier into scope:
Чтобы добавить в область видимости все идентификаторы пространства имен, используйте директиву using: Use a using directive to bring everything in the namespace into scope:
директивы using using directives
using Директива позволяет использовать все имена в namespace для использования без имени пространства имен в качестве явного квалификатора. The using directive allows all the names in a namespace to be used without the namespace-name as an explicit qualifier. Использование директивы using в файле реализации (т. е. *. cpp) при использовании нескольких различных идентификаторов в пространстве имен; Если вы используете только один или два идентификатора, рассмотрите использование объявления using, чтобы привести эти идентификаторы в область, а не все идентификаторы в пространстве имен. Use a using directive in an implementation file (i.e. *.cpp) if you are using several different identifiers in a namespace; if you are just using one or two identifiers, then consider a using declaration to only bring those identifiers into scope and not all the identifiers in the namespace. Если локальная переменная имеет такое же имя, как и переменная пространства имен, то переменная пространства имен будет скрытой. If a local variable has the same name as a namespace variable, the namespace variable is hidden. Создавать переменную пространства имен с те же именем, что и у глобальной переменной, является ошибкой. It is an error to have a namespace variable with the same name as a global variable.
Без особой необходимости не размещайте директивы using в файлах заголовков (*.h), так как любой файл, содержащий этот заголовок, добавит все идентификаторы пространства имен в область видимости, что может вызвать скрытие или конфликты имен, которые очень трудно отлаживать. In general, avoid putting using directives in header files (*.h) because any file that includes that header will bring everything in the namespace into scope, which can cause name hiding and name collision problems that are very difficult to debug. В файлах заголовков всегда используйте полные имена. Always use fully qualified names in a header file. Если эти имена получаются слишком длинными, используйте псевдоним пространства имен для их сокращения. If those names get too long, you can use a namespace alias to shorten them. (См. ниже.) (See below.)
Объявление пространств имен и их членов Declaring namespaces and namespace members
Как правило, пространство имен объявляется в файле заголовка. Typically, you declare a namespace in a header file. Если реализации функций находятся в отдельном файле, определяйте имена функций полностью, как показано в следующем примере. If your function implementations are in a separate file, then qualify the function names, as in this example.
Реализации функций в контосодата. cpp должны использовать полное имя, даже если поместить using директиву в начало файла: Function implementations in contosodata.cpp should use the fully qualified name, even if you place a using directive at the top of the file:
Пространство имен может быть объявлено в нескольких блоках в одном файле и в нескольких файлах. A namespace can be declared in multiple blocks in a single file, and in multiple files. Компилятор соединит вместе все части во время предварительной обработки и полученное в результате пространство имен будет содержать все члены, объявленные во всех частях. The compiler joins the parts together during preprocessing and the resulting namespace contains all the members declared in all the parts. Примером этого является пространство имен std, которое объявляется в каждом из файлов заголовка в стандартной библиотеке. An example of this is the std namespace which is declared in each of the header files in the standard library.
Члены именованного пространства имен могут определяться за его границами, если они объявлены путем явной квалификации определяемого пространства имен. Members of a named namespace can be defined outside the namespace in which they are declared by explicit qualification of the name being defined. Однако определение должно располагаться после точки объявления в пространстве имен, окружающем то пространство имен, где находится объявление. However, the definition must appear after the point of declaration in a namespace that encloses the declaration’s namespace. Пример: For example:
Эта ошибка может возникнуть, когда члены пространства имен объявляются в нескольких файлах заголовка и эти заголовки не включены в правильном порядке. This error can occur when namespace members are declared across multiple header files, and you have not included those headers in the correct order.
Глобальное пространство имен The global namespace
Пространство имен std The std namespace
Вложенные пространства имен Nested namespaces
Пространства имен могут быть вложенными. Namespaces may be nested. Обычное вложенное пространство имен имеет неполный доступ к членам родительского элемента, но родительские элементы не имеют неполного доступа к вложенному пространству имен (если только оно не объявлено как встроенное), как показано в следующем примере: An ordinary nested namespace has unqualified access to its parent’s members, but the parent members do not have unqualified access to the nested namespace (unless it is declared as inline), as shown in the following example:
Обычные вложенные пространства имен можно использовать для инкапсуляции данных о внутренней реализации, которые не являются частью открытого интерфейса родительского пространства имен. Ordinary nested namespaces can be used to encapsulate internal implementation details that are not part of the public interface of the parent namespace.
Встроенные пространства имен (C++ 11) Inline namespaces (C++ 11)
В отличие от обычных вложенных пространств имен члены встроенного пространства имен обрабатываются как члены родительского пространства имен. In contrast to an ordinary nested namespace, members of an inline namespace are treated as members of the parent namespace. Эта особенность позволяет выполнять поиск перегруженных функций с зависимостью от аргументов среди функции, которые имеют перегрузки в родительском и вложенном встроенном пространстве имен. This characteristic enables argument dependent lookup on overloaded functions to work on functions that have overloads in a parent and a nested inline namespace. Это также позволяет объявлять специализации в родительском пространстве имен для шаблонов, объявленных во встроенном пространстве имен. It also enables you to declare a specialization in a parent namespace for a template that is declared in the inline namespace. В следующем примере показано, как внешний код привязывается к встроенному пространству имен по умолчанию. The following example shows how external code binds to the inline namespace by default:
В следующем примере показано, как можно объявить специализацию в родительском пространстве имен шаблона, объявленного во встроенном пространстве имен. The following example shows how you can declare a specialization in a parent of a template that is declared in an inline namespace:
Встроенные пространства имен можно использовать как механизм управления версиями для управления изменениями в открытом интерфейсе библиотеки. You can use inline namespaces as a versioning mechanism to manage changes to the public interface of a library. Например, можно создать одно родительское пространство имен и инкапсулировать каждую версию интерфейса в своем собственном пространстве имен, вложенном в родительское. For example, you can create a single parent namespace, and encapsulate each version of the interface in its own namespace nested inside the parent. Пространство имен, которое содержит самую последнюю или основную версию, квалифицируется как встроенное и поэтому представляется так, будто оно является непосредственным членом родительского пространства имен. The namespace that holds the most recent or preferred version is qualified as inline, and is therefore exposed as if it were a direct member of the parent namespace. Клиентский код, вызывающий Parent::Class, автоматически привязывается к новому коду. Client code that invokes the Parent::Class will automatically bind to the new code. Клиенты, которые предпочитают использовать старую версию, могут по-прежнему получить доступ к ней, используя полный путь к вложенному пространству имен, содержащему данный код. Clients that prefer to use the older version can still access it by using the fully qualified path to the nested namespace that has that code.
Ключевое слово inline должно применяться к первому объявлению пространства имен в единице компиляции. The inline keyword must be applied to the first declaration of the namespace in a compilation unit.
Псевдонимы пространств имен Namespace aliases
Имена пространств имен должны быть уникальными, из-за чего зачастую они получаются не слишком короткими. Namespace names need to be unique, which means that often they should not be too short. Если длина имени затрудняет чтение кода или утомительно вводить файл заголовка, где нельзя использовать директивы using, можно создать псевдоним пространства имен, который служит аббревиатурой для фактического имени. If the length of a name makes code difficult to read, or is tedious to type in a header file where using directives can’t be used, then you can make a namespace alias which serves as an abbreviation for the actual name. Пример: For example:
анонимные или безымянные пространства имен anonymous or unnamed namespaces
Вы можете создать явное пространство имен, но не присвоить ему имя. You can create an explicit namespace but not give it a name: