using namespace std что это

Пространства имен (namespaces) в C++

Пространство имен в C ++ — это обобщенная область видимости. Его объявление начинается с зарезервированного слова namespace, за которым следует имя по выбору программиста, а затем блок в фигурных скобках. Блок содержит базовые объявления и / или определения объектов, функций и других сущностей C ++.

Рассмотрим следующие два скалярных оператора в глобальной области в следующей программе:

int varId = 5 ;
float varId = 2.3 ;

Попытка скомпилировать эту программу приводит к ошибке компиляции. Есть две переменные с одинаковым именем varId. Хотя это две разные переменные двух разных типов, int и float, компилятор отклоняет два объявления, потому что они имеют одно и то же имя. Следующая программа решает эту проблему, объявляя переменные с одинаковыми именами в двух разных обобщенных областях:

namespace NA
<
int varId = 5 ;
>

namespace NB
<
float varId = 2.3 ;
>

int main ( )
<
cout NA :: varId ‘ \n ‘ ;
cout NB :: varId ‘ \n ‘ ;

Результат выглядит следующим образом:

В этой статье рассматривается основная концепция пространства имен и его использование в языке программирования C ++. Чтобы следовать этой статье, вы должны иметь базовые знания языка C ++. Вы также должны знать область действия C ++, хотя она кратко объясняется в этой статье. Чтобы узнать больше о области действия C ++, найдите фразу «Область действия в C ++» (без кавычек) в поле поиска любой веб-страницы linuxhint.com и нажмите Enter. Это приведет вас к статье, написанной этим автором.

Что такое пространство имен?

Декларативная область — это самая большая часть программы, в которой допустимо имя объекта (переменной). Эта область называется областью действия. Пространство имен в C ++ — это обобщенная область видимости, основной целью которой является разрешение конфликтов имен. Пространство имен имеет базовые объявления и / или определения сущностей.

Глобальное пространство имен и его проблема

Глобальное пространство имен — это глобальная область видимости. Рассмотрим следующую короткую программу:

int ident = 55 ;
float ident = 12.17 ;

В приведенной выше программе есть две переменные, обе называемые идентификатором. Эти переменные находятся в глобальной области видимости; то есть они находятся в глобальном пространстве имен. Попытка скомпилировать эту программу завершится ошибкой. Глобальная область видимости не принимает более одной переменной с одинаковым именем, поэтому существует необходимость в настраиваемом пространстве имен.

Пользовательское пространство имен

namespace NA
<
int varInt = 6 ;
float flt ;
>

namespace NB
<
int varInt = 7 ;
float flt ;
>

int main ( )
<
cout NA :: varInt ‘ \n ‘ ;
cout NB :: varInt ‘ \n ‘ ;
NA :: flt = 2.5 ;
NB :: flt = 4.8 ;
cout NA :: flt ‘ \n ‘ ;
cout NB :: flt ‘ \n ‘ ;

Обратите внимание, что имена NA :: flt и NB :: flt в конечном итоге определены в функции main (). C ++ не допускает такого определения в глобальной области видимости.

Обратите внимание, что настраиваемое пространство имен является вложенным пространством имен для глобального пространства имен.

Директива использования

Чтобы не вводить все время «namepace :: name» вместо просто «name» после объявления пространства имен, вы можете использовать директиву using. Синтаксис использования директивы using следующий:

С помощью директивы не директива препроцессора, поэтому она заканчивается точкой с запятой (;).

Следующая программа иллюстрирует использование директивы using и др.:

namespace NB
<
int varInt = 7 ;
int func ( )
<
return varInt ;
>
>

int fn ( )
<
using namespace NB ;
int myVar2 = func ( ) ;
//other objects and functions from NB follow.
return myVar2 ;
>

int myVar3 = NB :: func ( ) ;

int main ( )
<
cout fn ( ) ‘ ‘ myVar3 ‘ \n ‘ ;

Переменная, объявленная в глобальной области (глобальном пространстве имен), просматривается от точки объявления до конца файла. Это также видно во вложенных пространствах имен (вложенных областях), таких как вложенная область видимости функции fn () выше. С помощью директивы соединяет его пространство имен из позиции, в которой он размещен в конце области, в которой он размещен.

Имя func () из пространства имен NB нельзя увидеть под определением fn (), потому что » using namespace NB;» был помещен в область действия функции (блок). При этом условии, чтобы использовать функцию » func () » вне блока (области) пространства имен NB, ему должен предшествовать » NB :: «, как в следующем операторе:

С помощью директивы присоединяется своим пространством имен с внешним гнездовым пространством именами из положения, в котором он находится на конец внешних вложенности имен. В следующей программе пространство имен NA объединено с глобальным пространством имен. Оба пространства имен затем расширяются в пространство имен определения функции fn (), в котором они объединяются с пространством имен NB. Пространство имен NB заканчивается в конце определения функции fn (), а два предыдущих пространства имен продолжаются до конца файла (считывания кода).

namespace NA
<
int varInt = 6 ;
int func ( )
<
return varInt ;
>

namespace NB
<
int varInt = 7 ;
int func ( )
<
return varInt ;
>
>

using namespace NA ;
int myVar0 = varInt ;
//other objects and functions from :: and NB follow.

int fn ( )
<
int myVar1 = varInt ;
using namespace NB ;
int myVar2 = NB :: func ( ) ;
//other objects and functions from NB follow, till end of this scope.
return myVar1 + myVar2 ;
>

//Only objects and functions from :: and NB follow.

int myVar3 = NB :: func ( ) ;

int main ( )
<
cout myVar0 ‘ ‘ fn ( ) ‘ ‘ myVar3 ‘ \n ‘ ;

На выходе будет 6, 13, 7.

Под утверждением » using namespace NA; «Переменные из глобального пространства имен и пространства имен NA могут использоваться без указания их исходного пространства имен. Следующий оператор использует varInt пространства имен NA. Область объединенного пространства имен global и NA простирается в пространство имен функции fn (). Итак, varInt первого оператора в области видимости функции fn () относится к пространству имен NA.

Поскольку область для глобального пространства имен и пространства имен NA распространяется на всю область видимости fn (), после » int myVar2 = NB :: func ();, «Любое имя из пространства имен NB может использоваться только в области fn () без предшествующего ему» NB :: «, только если оно не встречается в NA и глобальных пространствах имен (блоках). В противном случае ему должно предшествовать » NB :: «. Область объединенных пространств имен для NA и global продолжается ниже определения fn () и в функцию main () до конца файла.

Расширение пространства имен NB начинается с » int myVar2 = NB :: func (); «В блоке fn () и заканчивается в конце блока определения fn ().

Читайте также:  айнил для собак для чего

Примечание: Пространства имен, регионы которых соединяются, не должны иметь одинаковые имена переменных в разных блоках пространств имен, так как это все равно вызовет конфликт.

Области пространства имен

Пространство имен — это область видимости. Помимо глобального пространства имен (глобальная область видимости), любое пространство имен должно быть объявлено в блоке. Этот блок является первой частью возможных распределенных областей пространства имен. С помощью директивы using пространство имен может быть расширено как регионы в других областях.

Объекты, объявленные в теле пространства имен, называются членами этого пространства имен, а имена, введенные этими объявлениями в декларативную область пространства имен, называются именами членов этого пространства имен.

Вложенные пространства имен

Следующая программа показывает вложенные пространства имен:

namespace A
<
int i = 1 ;
namespace B
<
int i = 2 ;
namespace C
<
int i = 3 ;
>
>
>

int main ( )
<
cout A :: i ‘ ‘ A :: B :: i ‘ ‘ A :: B :: C :: i ‘ \n ‘ ;

Обратите внимание, что доступ к трем значениям был осуществлен с помощью оператора разрешения области видимости.

Стандартное пространство имен

В C ++ есть библиотека, называемая стандартной библиотекой. Имена объектов, функций и других сущностей в этой библиотеке взяты из пространства имен, называемого стандартным пространством имен, записанного как std. Стандартная библиотека содержит подбиблиотеки, и одна из этих подбиблиотек — iostream. Библиотека iostream содержит объект cout, который используется для отправки результатов на консоль (терминал).

Имя cout должно находиться в пространстве имен std. Чтобы использовать iostream с его пространством имен std, программа должна быть следующей:

Обратите внимание на использование директивы using и std. Термин » #include » является директивой препроцессора и не заканчивается точкой с запятой. Он включает в себя «файл» iostream в позиции своей директивы.

Заключение

Пространство имен — это область видимости. Описание (определение) пространства имен содержит базовые объявления и / или определения объектов, функций и других сущностей C ++. Вне определения пространства имен доступ к имени можно получить с помощью синтаксиса » namespaceName :: name «. Помимо глобального пространства имен (глобальная область видимости), любое пространство имен должно быть объявлено в блоке. Этот блок является первой частью возможных распределенных областей пространства имен. С помощью директивы using пространство имен может быть расширено как регионы в других областях. Пространства имен, регионы которых соединяются, не должны иметь одинаковые имена переменных в разных блоках пространств имен, так как это все равно вызовет конфликт имен.

Источник

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:

Use a using declaration to bring one identifier into scope:

Use a using directive to bring everything in the namespace into scope:

using directives

The using directive allows all the names in a namespace to be used without the namespace-name as an explicit qualifier. 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.

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.

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. 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

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.

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. 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.

Читайте также:  арболит на что крепится

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. 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:

Источник

Использование пространства имен std

Кажется, существуют разные взгляды на использование слова using в отношении пространства имен std.

Некоторые говорят использовать ‘ using namespace std ‘, другие говорят, что нет, а вместо этого используют префикс std-функций, которые должны использоваться с ‘ std:: ‘, в то время как другие говорят, что используйте что-то вроде этого:

для всех std-функций, которые будут использоваться.

Каковы плюсы и минусы каждого из них?

Ошибка обычно длинная и недружелюбная, потому что std::count это шаблон с некоторыми длинными вложенными типами.

Это нормально, потому что std::count входит в глобальное пространство имен, а счетчик функций скрывает его.

Исключение основ (необходимость добавления std :: infront всех объектов / функций stl и меньшая вероятность конфликта, если у вас нет ‘using namespace std’)

Также стоит отметить, что никогда не следует ставить

В файле заголовка, поскольку он может распространяться на все файлы, которые включают этот файл заголовка, даже если они не хотят использовать это пространство имен.

В некоторых случаях очень полезно использовать такие вещи, как

Сначала немного терминологии:

Точно так же, если вы можете обойтись несколькими объявлениями using (вместо директив using ) для определенных типов в std пространстве имен, тогда нет причин, по которым вы не должны иметь только эти конкретные имена, перенесенные в текущее пространство имен. К тому же, я думаю, что было бы безумием и хлопотно иметь дело с 25 или 30 объявлениями using, когда одна директива using также подойдет.

Также хорошо иметь в виду, что бывают случаи, когда вы должны использовать объявление using. Обратитесь к статье 25 Скотта Мейерса: подумайте о поддержке безбрасывающего свопа из Эффективного C ++, Третье издание. Чтобы универсальная шаблонная функция использовала «лучший» метод подкачки для параметризованного типа, вам необходимо использовать объявление с использованием объявления и поиск, зависящий от аргументов (также известный как ADL или поиск по Кенигу):

Херб Саттер и Андрей Александреску говорят об этом в «Правиле 59: Не записывайте использование пространств имен в заголовочный файл или перед #include» своей книги «Стандарты кодирования C ++: 101 правила, рекомендации и лучшие практики»:

Вкратце: вы можете и должны использовать пространство имен, используя объявления и директивы в ваших файлах реализации после #include директив, и вам это нравится. Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, они делают пространства имен пригодными для использования.

Струпструп часто цитируется как сказал: «Не загрязняйте глобальное пространство имен» в «Языке программирования C ++, третье издание». Он действительно так говорит (C.14 [15]), но ссылается на главу C.10.1, где говорит:

Объявление using добавляет имя в локальную область видимости. С помощью директивы не делает; он просто делает имена доступными в той области, в которой они были объявлены. Например:

Локально объявленное имя (объявленное обычным объявлением или использованием-объявлением) скрывает нелокальные объявления с тем же именем, а любые незаконные перегрузки имени обнаруживаются в точке объявления.

Когда библиотеки, объявляющие много имен, становятся доступными с помощью директив using, существенным преимуществом является то, что конфликты неиспользуемых имен не считаются ошибками.

Я надеюсь увидеть радикальное сокращение использования глобальных имен в новых программах, использующих пространства имен, по сравнению с традиционными программами на C и C ++. Правила для пространств имен были специально созданы, чтобы не давать преимуществ «ленивому» пользователю глобальных имен перед тем, кто заботится о том, чтобы не загрязнять глобальную область видимости.

И как получить такое же преимущество, как «ленивый пользователь глобальных имен»? Используя преимущество директивы using, которая безопасно делает имена в пространстве имен доступными для текущей области.

Источник

Namespaces

Compiler support
Freestanding and hosted
Language
Standard library headers
Named requirements
Feature test macros (C++20)
Language support library
Concepts library (C++20)
Diagnostics library
General utilities library
Strings library
Containers library
Iterators library
Ranges library (C++20)
Algorithms library
Numerics library
Localizations library
Input/output library
Filesystem library (C++17)
Regular expressions library (C++11)
Atomic operations library (C++11)
Thread support library (C++11)
Technical specifications
Symbols index
External libraries
Declarators
reference
pointer
array
Block declarations
simple-declaration
→ structured binding declaration (C++17)
alias declaration (C++11)
namespace alias definition
using-declaration
using-directive
static_assert declaration (C++11)
asm-declaration
opaque enum declaration (C++11)
Other declarations
namespace definition
function declaration
class template declaration
function template declaration
explicit template instantiation (C++11)
explicit template specialization
linkage specification
attribute declaration (C++11)
empty declaration

Namespaces provide a method for preventing name conflicts in large projects.

Symbols declared inside a namespace block are placed in a named scope that prevents them from being mistaken for identically-named symbols in other scopes.

Multiple namespace blocks with the same name are allowed. All declarations within those blocks are declared in the named scope.

Contents

[edit] Syntax

namespace ns_name (1)
inline namespace ns_name (2) (since C++11)
namespace (3)
ns_name :: name (4)
using namespace ns_name ; (5)
using ns_name :: name ; (6)
namespace name = qualified-namespace ; (7)
namespace ns_name :: name (8) (since C++17)
namespace ns_name :: inline name (9) (since C++20)

[edit] Explanation

[edit] Namespaces

Namespace definitions are only allowed at namespace scope, including the global scope.

To reopen an existing namespace (formally, to be an extension-namespace-definition), the lookup for the identifier used in the namespace definition must resolve to a namespace name (not a namespace alias), that was declared as a member of the enclosing namespace or of an inline namespace within an enclosing namespace.

The namespace-body defines a namespace scope, which affects name lookup.

A namespace member that was declared within a namespace body may be defined or redeclared outside of it using explicit qualification

Out-of-namespace definitions and redeclarations are only allowed

Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to ordinary name lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.

Only the innermost enclosing namespace is considered by such friend declaration when deciding whether the name would conflict with a previously declared name.

Inline namespaces

An inline namespace is a namespace that uses the optional keyword inline in its original-namespace-definition.

Members of an inline namespace are treated as if they are members of the enclosing namespace in many situations (listed below). This property is transitive: if a namespace N contains an inline namespace M, which in turn contains an inline namespace O, then the members of O can be used as though they were members of M or N.

Note: the rule about specializations allows library versioning: different implementations of a library template may be defined in different inline namespaces, while still allowing the user to extend the parent namespace with an explicit specialization of the primary template.

[edit] Unnamed namespaces

The unnamed-namespace-definition is a namespace definition of the form

inline (optional) namespace attr (optional) < namespace-body >
inline (since C++11) if present, makes this an inline namespace
attr (since C++17) optional sequence of any number of attributes

This definition is treated as a definition of a namespace with unique name and a using-directive in the current scope that nominates this unnamed namespace (Note: implicitly added using directive makes namespace available for the qualified name lookup and unqualified name lookup, but not for the argument-dependent lookup ).

Even though names in an unnamed namespace may be declared with external linkage, they are never accessible from other translation units because their namespace name is unique.

Unnamed namespaces as well as all namespaces declared directly or indirectly within an unnamed namespace have internal linkage, which means that any name that is declared within an unnamed namespace has internal linkage.

[edit] Using-declarations

Introduces a name that is defined elsewhere into the declarative region where this using-declaration appears.

A using-declaration with more than one using-declarator is equivalent to a corresponding sequence of using-declarations with one using-declarator.

For the use in derived class definitions, see using declaration.

Names introduced into a namespace scope by a using-declaration can be used just like any other names, including qualified lookup from other scopes:

If, after the using-declaration was used to take a member from a namespace, the namespace is extended and additional declarations for the same name are introduced, those additional declarations do not become visible through the using-declaration (in contrast with using-directive). One exception is when a using-declaration names a class template: partial specializations introduced later are effectively visible, because their lookup proceeds through the primary template.

All restrictions on regular declarations of the same names, hiding, and overloading rules apply to using-declarations:

If a function was introduced by a using-declaration, declaring a function with the same name and parameter list is ill-formed (unless the declaration is for the same function). If a function template was introduced by a using-declaration, declaring a function template with the same name, parameter type list, return type, and template parameter list is ill-formed. Two using-declarations can introduce functions with the same name and parameter list, but if a call to that function is attempted, the program is ill-formed.

If an entity is declared, but not defined in some inner namespace, and then declared through using-declaration in the outer namespace, and then a definition appears in the outer namespace with the same unqualified name, that definition is a member of the outer namespace and conflicts with the using-declration:

More generally, a declaration that appears in any namespace scope and introduces a name using an unqualified identifier always introduces a member into the namespace it’s in and not to any other namespace. The exceptions are explicit instantiations and explicit specializations of a primary template that is defined in an inline namespace: because they do not introduce a new name, they may use unqualified-id in an enclosing namespace.

[edit] Using-directives

A using-directive is a block-declaration with the following syntax:

Using-directive does not add any names to the declarative region in which it appears (unlike the using-declaration), and thus does not prevent identical names from being declared.

If, after a using-directive was used to nominate some namespace, the namespace is extended and additional members and/or using-directives are added to it, those additional members and the additional namespaces are visible through the using-directive (in contrast with using-declaration)

[edit] Notes

The using-directive using namespace std ; at any namespace scope introduces every name from the namespace std into the global namespace (since the global namespace is the nearest namespace that contains both std and any user-declared namespace), which may lead to undesirable name collisions. This, and other using directives are generally considered bad practice at file scope of a header file (SF.7: Don’t write using namespace at global scope in a header file).

[edit] Example

This example shows how to use a namespace to create a class that already has been named in the std namespace.

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 1838 C++14 unqualified definition in an outer namespace could define an entity declared,

but not defined in another namespace and pulled in by a using

Источник

Читайте также:  бодиплетизмография легких что это такое
Информ портал о технике и не только