Я пришел из Java, где используются пакеты, а не пространства имен. Я привык помещать классы, которые работают вместе, чтобы сформировать законченный объект в пакеты, а затем повторно использовать их позже из этого пакета. Но сейчас я работаю в C ++.
Как вы используете пространства имен в C ++? Вы создаете единое пространство имен для всего приложения или вы создаете пространства имен для основных компонентов? Если да, то как вы создаете объекты из классов в других пространствах имен?
источник
std
пространства имен к символам, а не использовать егоusing
вообще. Так что я всегда пишуstd::cout
илиstd::string
сейчас, потому что так я их сейчас называю. Я бы никогда не написалcout
.std
, я лично нашел это гораздо менее важным, когда вы имеете дело с небольшими библиотеками. Часто вы можете просто использоватьusing namespace FooBario;
, особенно если вы используете значительное количество типов из библиотеки.using namespace X;
следует избегать в заголовочных файлах, если это возможно.mylibrary::endl
для представления своей собственной специальной последовательности новой строки. Я имею в виду, зачем придумывать имена?Чтобы не говорить ничего, Марк Ингрэм уже сказал небольшой совет по использованию пространств имен:
Избегайте директивы using namespace в заголовочных файлах - это открывает пространство имен для всех частей программы, которые импортируют этот заголовочный файл. В файлах реализации (* .cpp) это обычно не представляет большой проблемы - хотя я предпочитаю использовать директиву "using namespace" на уровне функций.
Я думаю, что пространства имен в основном используются, чтобы избежать конфликтов имен - не обязательно для организации структуры кода. Я бы организовал программы на C ++ в основном с заголовочными файлами / файловой структурой.
Иногда пространства имен используются в больших проектах C ++, чтобы скрыть детали реализации.
Дополнительное примечание к директиве using: Некоторые люди предпочитают использовать «using» только для отдельных элементов:
источник
using std::cout;
является декларацией об использованииusing std::cout, std::endl;
или дажеusing std::cout, endl;
.using namespace x
заголовок, если он находится в другом пространстве имен. Это не то, что я бы рекомендовал в целом, но оно не загрязняет глобальное пространство имен.Винсент Роберт прав в своем комментарии. Как правильно использовать пространства имен в C ++? ,
Использование пространства имен
Пространства имен используются, по крайней мере, чтобы избежать конфликта имен. В Java это обеспечивается с помощью идиомы «org.domain» (поскольку предполагается, что никто не будет использовать ничего, кроме своего собственного доменного имени).
В C ++ вы можете дать пространство имен всему коду в вашем модуле. Например, для модуля MyModule.dll вы можете дать его коду пространство имен MyModule. Я видел в другом месте, кто-то использует MyCompany :: MyProject :: MyModule. Я думаю, это излишне, но в целом мне кажется правильным.
Используя "использование"
Использование должно использоваться с большой осторожностью, потому что оно эффективно импортирует один (или все) символы из пространства имен в ваше текущее пространство имен.
Это плохо делать в заголовочном файле, потому что ваш заголовок будет загрязнять каждый источник, включая его (это напоминает мне макросы ...), и даже в исходном файле плохой стиль выходит за пределы области действия функции, поскольку он будет импортироваться в глобальном контексте. символы из пространства имен.
Самый безопасный способ использовать «использование» - это импортировать выбранные символы:
Вы увидите много «использования пространства имен std;» в учебных или примерных кодах. Причина в том, чтобы уменьшить количество символов, чтобы облегчить чтение, а не потому, что это хорошая идея.
"использование пространства имен std;" обескуражен Скоттом Мейерсом (я не помню точно, какую книгу, но я могу найти ее в случае необходимости).
Композиция пространства имен
Пространства имен - это больше, чем пакеты. Другой пример можно найти в книге Бьярна Страуструпа «Язык программирования C ++».
В «Специальном издании», в 8.2.8 Состав пространства имен , он описывает, как вы можете объединить два пространства имен AAA и BBB в другое, называемое CCC. Таким образом, CCC становится псевдонимом для AAA и BBB:
Вы даже можете импортировать выбранные символы из разных пространств имен, чтобы создать свой собственный интерфейс пространства имен. Мне еще предстоит найти практическое применение этому, но в теории это круто.
источник
Я не видел никакого упоминания об этом в других ответах, поэтому вот мои 2 канадских цента:
В разделе «Использование пространства имен» полезным является псевдоним пространства имен, позволяющий вам «переименовать» пространство имен, обычно, чтобы дать ему более короткое имя. Например, вместо:
ты можешь написать:
источник
Не слушайте, чтобы все люди говорили вам, что пространства имен - это просто пространства имен.
Они важны, потому что они рассматриваются компилятором для применения принципа интерфейса. В основном это можно объяснить на примере:
Если вы хотите напечатать объект A, код будет таким:
Обратите внимание, что мы явно не упоминали пространство имен при вызове функции. Это принцип интерфейса: C ++ рассматривает функцию, принимающую тип в качестве аргумента, как часть интерфейса для этого типа, поэтому нет необходимости указывать пространство имен, поскольку параметр уже подразумевает пространство имен.
Теперь, почему этот принцип важен? Представьте, что автор класса А не предоставил функцию print () для этого класса. Вы должны будете предоставить один самостоятельно. Поскольку вы хороший программист, вы определите эту функцию в своем собственном пространстве имен или, возможно, в глобальном пространстве имен.
И ваш код может начать вызывать функцию print (a) где угодно. Теперь представьте, что спустя годы автор решает предоставить функцию print () лучше, чем ваша, потому что он знает внутренности своего класса и может сделать лучшую версию, чем ваша.
Затем авторы C ++ решили, что его версия функции print () должна использоваться вместо той, которая представлена в другом пространстве имен, для соблюдения принципа интерфейса. И что это «обновление» функции print () должно быть максимально простым, а это означает, что вам не придется менять каждый вызов функции print (). Вот почему «интерфейсные функции» (функции в том же пространстве имен, что и у класса) можно вызывать без указания пространства имен в C ++.
И именно поэтому вы должны рассматривать пространство имен C ++ как «интерфейс», когда используете его, и иметь в виду принцип интерфейса.
Если вы хотите получить лучшее объяснение этого поведения, вы можете обратиться к книге « Исключительный C ++» от Херба Саттера.
источник
На самом деле boost использует тонны пространств имен, обычно каждая часть boost имеет свое собственное пространство имен для внутренней работы, а затем может поместить только публичный интерфейс в повышение пространства имен верхнего уровня.
Лично я считаю, что чем больше становится кодовая база, тем важнее становятся пространства имен даже внутри одного приложения (или библиотеки). На работе мы помещаем каждый модуль нашего приложения в свое собственное пространство имен.
Другое использование (без каламбура) пространств имен, которое я часто использую, - это анонимное пространство имен:
Это в основном так же, как:
Однако рекомендуется использовать анонимное пространство имен (вместо статического), чтобы код и данные были видны только в текущем модуле компиляции в C ++.
источник
const int CONSTANT = 42;
поскольку const верхнего уровня в области именного пространства уже подразумевает внутреннюю связь. Таким образом, вам не нужно анонимное пространство имен в этом случае.Также обратите внимание, что вы можете добавить в пространство имен. Это яснее с примером, я имею в виду, что вы можете иметь:
в файле
square.h
, ив файле
cube.h
. Это определяет одно пространство именMyNamespace
(то есть вы можете определить одно пространство имен для нескольких файлов).источник
В Java:
В C ++:
И используя их, Java:
И C ++:
Также полными именами являются «somepackge.SomeClass» для Java и «somenamespace :: SomeClass» для C ++. Используя эти соглашения, вы можете организовать, как вы привыкли в Java, включая создание соответствующих имен папок для пространств имен. Требования к папкам -> пакетам и файлам -> классам не существуют, так что вы можете именовать свои папки и классы независимо от пакетов и пространств имен.
источник
@ Мариус
Да, вы можете использовать несколько пространств имен одновременно, например:
[Февраль 2014 - (Это действительно было так долго?): Этот конкретный пример сейчас неоднозначен, как Джои указывает ниже. Boost и std :: теперь у каждого есть shared_ptr.]
источник
std
также имеетshared_ptr
место, поэтому использование обоихboost
иstd
пространств имен будет конфликтовать, когда вы попытаетесь использовать ashared_ptr
.Вы также можете содержать «using namespace ...» внутри функции, например:
источник
Вообще говоря, я создаю пространство имен для тела кода, если считаю, что могут быть конфликты имен функций или типов с другими библиотеками. Это также помогает маркировать код, аля повысить :: .
источник
Я предпочитаю использовать пространство имен верхнего уровня для приложения и подпространства имен для компонентов.
То, как вы можете использовать классы из других пространств имен, на удивление очень похоже на то, как в Java. Вы можете использовать «use NAMESPACE», которое похоже на оператор «import PACKAGE», например, использовать std. Или вы указываете пакет как префикс класса, разделенного "::", например, std :: string. Это похоже на «java.lang.String» в Java.
источник
Обратите внимание, что пространство имен в C ++ на самом деле является просто пространством имен. Они не обеспечивают никакой инкапсуляции, которую делают пакеты в Java, поэтому вы, вероятно, не будете использовать их так часто.
источник
Я использовал пространства имен C ++ так же, как и в C #, Perl и т. Д. Это просто семантическое разделение символов между стандартными библиотечными материалами, сторонними компонентами и моим собственным кодом. Я бы поместил свое собственное приложение в одно пространство имен, а затем повторно используемый библиотечный компонент в другом пространстве имен для разделения.
источник
Другое отличие между Java и C ++ заключается в том, что в C ++ иерархия пространства имен не нуждается в обработке структуры файловой системы. Поэтому я склонен помещать всю библиотеку многократного использования в одно пространство имен, а подсистемы внутри библиотеки - в подкаталоги:
Я бы поместил подсистемы во вложенные пространства имен только в случае возможности конфликта имен.
источник