Using namespace std для чего

6.12 – Объявления using и директивы using

Вы, наверное, видели эту программу во многих учебниках и учебных руководствах:

Некоторые старые компиляторы также начинают новые проекты с аналогичной программы.

Если вы это видите, бегите. Возможно, ваш учебник, руководство или компилятор устарели. В этом уроке мы выясним, почему.

Краткий урок истории

Перенесемся в сегодняшний день – если вы много используете стандартную библиотеку, набирание std:: перед всем, что вы используете из стандартной библиотеки, может стать повторяющейся рутиной, а в некоторых случаях может затруднить чтение вашего кода.

Но сначала давайте определим два термина.

Полные и неполные имена

Имя может быть полным или неполным.

Полное имя – это имя, которое включает в себя связанную область видимости. Чаще всего имена дополняются пространством имен с помощью оператора разрешения области видимости ( :: ). Например:

Для продвинутых читателей

Неполное имя – это имя, которое не включает в себя квалификатор области видимости. Например, cout и x являются неполными именами, поскольку они не включают связанную область видимости.

Объявления using

Директивы using

Вот снова наша программа Hello World с директивой using в строке 5:

Директивы using – это решение, которое было предоставлено для баз старого кода до пространства имен, которые использовали неполные имена для функций стандартной библиотеки. Вместо того, чтобы вручную обновлять каждое неполное имя до полного имени (что было рискованно), можно было бы разместить одну директиву using (т.е. using namespace std; ) в верхней части каждого файла, и все имена, которые были перемещены в пространство имен std всё еще можно было использовать неполными.

Проблемы с директивами using

Однако для современного кода C++ директивы using дают немного выгоды (экономия на вводе текста) по сравнению с риском.

Поскольку директивы using импортируют все имена из пространства имен (потенциально включая множество имен, которые вы никогда не будете использовать), вероятность возникновения конфликтов имен значительно возрастает (особенно, если вы импортируете пространство имен std ).

Для наглядности рассмотрим пример, в котором директивы using вызывают неоднозначность:

Вот еще один более коварный пример:

или использовалось объявление using вместо директивы using :

тогда наша программа вообще не имела бы никаких проблем.

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

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

Рассмотрим следующую программу:

Когда компилятор встречает вызов функции, он должен определить, с каким определением функции он должен сопоставить этот вызов. При выборе функции из набора потенциально совпадающих функций он предпочтет ту функцию, которая не требует преобразования аргументов, а не ту, которая требует преобразования аргументов. Поскольку литерал 0 принадлежит целочисленному типу, C++ предпочтет сопоставить someFcn(0) с недавно добавленной someFcn(int) (без преобразований), а не с someFcn(double) (требуется преобразование из int в double). Это вызывает неожиданное изменение результатов работы нашей программы.

Этого бы не произошло, если бы мы использовали объявление using или явный квалификатор области видимости.

Область видимости объявлений и директив using

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

Если объявление using или директива using используются в глобальном пространстве имен, имена применимы ко всему остальному файлу (они имеют область видимости файла).

Отмена или замена инструкции using

После объявления инструкции using ее невозможно отменить или заменить ее другой инструкцией using в той области видимости, в которой она была объявлена.

Лучшее, что вы можете сделать, – это намеренно с самого начала ограничить область видимости инструкции using с помощью правил области видимости блока.

Конечно, всей этой головной боли можно избежать, в первую очередь, используя явным образом оператор разрешения области видимости ( :: ).

Лучшие практики для инструкций using

В современном C++ на самом деле нет места для использования директив. Они увеличивают вероятность коллизий имен сейчас и в будущем и могут вызывать более коварные проблемы. Хотя во многих учебниках и руководствах они широко используются, использования директив лучше вообще избегать.

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

Лучшая практика

Источник

Пространство имен (using namespace std;)

5 ответов 5

Зависит от традиций. Среди плюсовиков традиция «лучше перестраховаться, чем получить внезапные трудно отлаживаемые проблемы неизвестно где».

Явное указание пространства имён — это избавление от потенциальных проблем в будущем. Положим, вы подключили через using namespace два пространства имён. Всё замечательно, кратко, красиво.

А потом вышла новая версия одной из библиотек, и какие-то идентификаторы стали резолвиться по-другому, например, во второй библиотеке добавили функцию, которая к вашим аргументам подходит лучше, чем используемая вами ранее функция из первой библиотеки.

В лучшем случае ваш код не соберётся. Может упасть. А может так получиться, что ваш код перестанет работать у клиента в 1% случаев. Всё может быть.

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

Насколько это важно конкретно для вас — решать вам. Если у вас простой проектик и от силы пара сторонних библиотек (или вообще только стандартная библиотека), то можно не заморачиваться с явным указанием пространств имён. Если проект огромный, с десятками библиотек, то может оказаться более удобным (и наглядным) всегда указывать пространства имён.

Банальный пример: положим, вы пользуетесь только стандартной библиотекой и boost, поэтому решили везде писать:

. а теперь выходит новая версия стандартной библиотеки, в которой из boost перетащено много классов. И внезапно ваш код больше не компилируется.

В других языках другие традиции. Например, в C# почти всегда пишут краткие имена классов, и только в случае конфликтов явно указывают пространство имён или используют алиасы. Язык немного отличается: там нет функций вне классов. Это позволяет меньше терять читаемость и реже натыкаться на неожиданные конфликты.

Источник

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

Using namespace std для чего. Prostranstva imen namespaces v C. Using namespace std для чего фото. Using namespace std для чего-Prostranstva imen namespaces v C. картинка Using namespace std для чего. картинка Prostranstva imen namespaces v 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:

Источник

Using namespace std что это такое и как используется в Visual C++

Отвечая на вопрос, что такое using namespace std для началае следует отметить, что переводе с английского описываемый термин означает пространство имени, являющиеся областью декларации, необходимо для определения различных идентификационных форм: функций и зависимых/независимых переменных.

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

Using namespace std для чего. ROMANT1. Using namespace std для чего фото. Using namespace std для чего-ROMANT1. картинка Using namespace std для чего. картинка ROMANT1

Идентификаторы находятся в свободном доступе по отношению друг к другу. Они получают свободный доступ к независимым членам при эксплуатации полного именного формата.

Для этого крайне важно, чтобы объект содержал полную форму наименования using namespace std. Это важно, чтобы визуально понять, каким образом выглядит объявление, располагаясь в имени пространства.

Содержание:

Using namespace std для чего. post image. Using namespace std для чего фото. Using namespace std для чего-post image. картинка Using namespace std для чего. картинка post image

На изображении представлено несколько вариаций доступа к кодировкам, располагающихся в пределах и за его ограждениями:

Using namespace std для чего. 1 10. Using namespace std для чего фото. Using namespace std для чего-1 10. картинка Using namespace std для чего. картинка 1 10

Using namespace std для чего. 2 13. Using namespace std для чего фото. Using namespace std для чего-2 13. картинка Using namespace std для чего. картинка 2 13

Using namespace std для чего. 3 10. Using namespace std для чего фото. Using namespace std для чего-3 10. картинка Using namespace std для чего. картинка 3 10

Using namespace std для чего. 4 12. Using namespace std для чего фото. Using namespace std для чего-4 12. картинка Using namespace std для чего. картинка 4 12

Директива Using

Using директива разрешает эксплуатацию всех имеющихся имен, которые включены в пространство имени.

При этом указывать квалификатор нет необходимости.

В том случае, когда существует только пару имен, актуальным будет создание обыкновенного имени.

Тогда можно добавить только необходимые идентификаторы, а остальные не трогать.

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

Стоит принять во внимание, что создание переменных с одинаковым наименованием является недопустимым действием.

Совет! Для удобства использования, using директива может быть расположена в верхушке файла формата cpp., либо наоборот, помещается внутрь созданной библиотеки.

Чтобы обеспечить для себя максимально комфортные условия работы, можно поработать над размещением необходимых файлов.

Если нет крайней необходимости, то директиву using не стоит размещать в заголовках файлом формата H.

Это связано с тем, что при данном действии все идентификаторы станут активными в поле видимости, повышая вероятность возникновения конфликтности некоторых наименований.

Для файлов оптимальным решением станет использование полного наименования.

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

Читайте также:

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

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

Чтобы понимать, о каких действиях идет речь, стоит ознакомиться со следующим изображением:

Using namespace std для чего. 5 9. Using namespace std для чего фото. Using namespace std для чего-5 9. картинка Using namespace std для чего. картинка 5 9

Чтобы реализовать функцию contosodata формата cpp., также важно использовать полное наименование и в том случае, когда директива стоит в самом начале:

Using namespace std для чего. 6 8. Using namespace std для чего фото. Using namespace std для чего-6 8. картинка Using namespace std для чего. картинка 6 8

Using namespace std. может содержать объявления сразу в нескольких разделах, находящихся в одном и том же файле.

За счет компилятора происходит объединение всех элементов, пока происходит обработка данных.

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

Так, например, std., как правило, объявляется во всех заголовках доступных файлов, располагающихся в доступных библиотеках стандартного типа.

Что касается определения, то оно должно быть после объявления в пространстве имени, где оно создано.

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

Using namespace std для чего. 7 8. Using namespace std для чего фото. Using namespace std для чего-7 8. картинка Using namespace std для чего. картинка 7 8

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

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

Совет! Если нет острой необходимости, то рекомендуется избегать включения членов в пространство глобального типа.

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

Чтобы создать идентификатор глобального типа, необходимо задействовать соответствующий функционала видимости, ввиде полного наименования.

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

Источник

Добавить комментарий

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