Почему и как я должен использовать пространства имен в C ++? - PullRequest
25 голосов
/ 18 ноября 2010

Я никогда раньше не использовал пространства имен для своего кода. (Кроме использования функций STL)

  1. Есть ли какая-либо другая причина использовать пространства имен, кроме как для предотвращения конфликтов имен?
  2. Нужно ли включать декларации и определения в область пространства имен?

Ответы [ 6 ]

22 голосов
/ 18 ноября 2010

Одной из причин, которую часто упускают из виду, является то, что просто изменяя одну строку кода для выбора одного пространства имен над другим, вы можете выбрать альтернативный набор функций / переменных / типов / констант - например, другую версию протокола илимногопоточная и многопоточная поддержка, поддержка ОС для платформы X или Y - скомпилируйте и запустите.Такой же эффект может быть достигнут путем включения заголовка с разными объявлениями или с #defines и #ifdefs, но это грубо влияет на всю единицу перевода, и при связывании разных версий вы можете получить неопределенное поведение.С помощью пространств имен вы можете делать выборки с помощью пространства имен, которые применяются только в активном пространстве имен, или делать это с помощью псевдонима пространства имен, чтобы они применялись только там, где используется этот псевдоним, но на самом деле они разрешаются в различные символы компоновщика, поэтому могут быть объединены безнеопределенное поведение.Это можно использовать способом, аналогичным шаблонным политикам, но эффект более неявный, автоматический и распространяющийся - очень мощная языковая функция.


ОБНОВЛЕНИЕ: обращение к комментарию marcv81 ...

Почему бы не использовать интерфейс с двумя реализациями?

"интерфейс + реализации" - это концептуально то, что делает выбор пространства имен для псевдонима выше, но если вы имеете в виду время выполнения полиморфизм и виртуальная диспетчеризация:

  • результирующая библиотека или исполняемый файл не должны содержать все реализации и постоянно направлять вызовы выбранной во время выполнения

  • , поскольку одна реализация включена, компилятор может использовать множество оптимизаций, включая встраивание, устранение мертвого кода, и константы, отличающиеся между «реализациями», могут использоваться, например, для размеров массивов - что позволяет автоматическое выделение памяти вместо медленного динамического выделения

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

  • с пространствами именВы можете предоставить пользовательские функции и шаблоны, не являющиеся членами: это невозможно при виртуальной диспетчеризации (а функции, не являющиеся членами, помогают с перегрузкой симметричного оператора - например, поддерживают 22 + my_type, а также my_type + 22)

  • разные пространства имен могут указывать разные типы для использования в определенных целях (например, хеш-функция может возвращать 32-битное значение в одном пространстве имен, но 64-битное значение в другом), но виртуальный интерфейс должен иметь объединяющие статические типы, которыеозначает неуклюжую и косвенную косвенную передачу, такую ​​как boost::any или boost::variant, или наихудший выбор, когда старшие биты иногда бессмысленныобработка ошибок: с пространствами имен есть опция , чтобы просто не указыватьИдеальная функциональность в пространствах имен, где это не имеет смысла, обеспечивая принудительное выполнение необходимых усилий по переносу клиента во время компиляции

12 голосов
/ 18 ноября 2010

Здесь является веской причиной (кроме очевидного, изложенного вами).

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

Определения имен в пространстве имен могут предоставляться либо в том же пространстве имен, либо в любом из вмещающих пространств имен (с полностью определенными именами).

5 голосов
/ 18 ноября 2010

Это может помочь вам лучше понять.

например:

std::func <- all function/class from C++ standard library
lib1::func <- all function/class from specific library
module1::func <-- all function/class for a module of your system

Вы также можете думать об этом как о модуле в вашей системе.

Это также может быть полезно для написания документации (например: вы можете легко документировать сущность пространства имен в doxygen)

2 голосов
/ 18 ноября 2010

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

2 голосов
/ 18 ноября 2010
  1. Разве имена не являются достаточной причиной? Тонкости ADL, особенно с перегрузками операторов, являются другими.

  2. Это самый простой способ. Вы также можете добавлять префиксы к именам пространства имен, например, my_namespace :: name, при определении.

1 голос
/ 18 ноября 2010
  1. Ответ: Если вы когда-нибудь захотите перегрузить новые, разместить новые или удалить функции, вам нужно будет выполнять их в пространстве имен.Никто не хочет, чтобы вас заставляли использовать вашу новую версию, если они не требуют того, что вам нужно.
  2. Да
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...