Почему и как я должен использовать пространства имен в С++?
Я раньше не использовал пространства имен для своего кода. (Кроме использования функций STL)
- Кроме того, чтобы избежать конфликтов имен, есть ли другая причина использовать пространства имен?
- Должен ли я заключать обе декларации и определения в пространстве имен?
Ответы
Ответ 1
Здесь является хорошей причиной (кроме очевидного, заявленного вами).
Так как пространство имен может быть разборчивым и разбросано по единицам трансляции, их также можно использовать для ветки интерфейса от деталей реализации.
Определения имен в пространстве имен могут предоставляться либо в том же пространстве имен, либо в любом из охватывающих пространств имен (с полными именами).
Ответ 2
Одной из причин, по которым часто упускают из виду, является простое изменение одной строки кода для выбора одного пространства имен над другим, вы можете выбрать альтернативный набор функций/переменных/типов/констант - например, другую версию протокола или одно- многопоточная поддержка, поддержка ОС для платформы X или Y - компиляция и запуск. Такой же эффект может быть достигнут путем включения заголовка с различными объявлениями или с #defines
и #ifdefs
, но это грубо влияет на всю единицу перевода, и если вы связываете разные версии, вы можете получить поведение undefined. В пространствах имен вы можете сделать выбор путем использования пространства имен, которое применяется только в активном пространстве имен, или сделать это с помощью псевдонима пространства имен, поэтому они применяются только в том случае, если этот псевдоним используется, но они фактически разрешены к отдельным символам компоновщика, поэтому их можно комбинировать без undefined. Это можно использовать аналогично политикам шаблонов, но влияние более неявное, автоматическое и повсеместное - очень мощная функция языка.
UPDATE: обращение к комментарию marcv81...
Почему бы не использовать интерфейс с двумя реализациями?
"интерфейс + реализации" концептуально заключается в том, что делает выбор пространства имен псевдонимом выше, но если вы имеете в виду специфический полиморфизм времени выполнения и виртуальную диспетчеризацию:
-
результирующая библиотека или исполняемый файл не должны содержать все реализации и постоянно направлять вызовы к выбранному во время выполнения
-
поскольку одна реализация включает в себя компилятор, может использовать множество оптимизаций, включая inlining, удаление мертвого кода и константы, отличающиеся между "реализациями", могут использоваться, например, размеры массивов - возможность автоматического распределения памяти вместо более медленного динамического размещения
-
разные пространства имен должны поддерживать одну и ту же семантику использования, но не обязаны поддерживать тот же набор сигнатур функций, что и в случае виртуальной отправки
-
с пространствами имен вы можете предоставить пользовательские функции и шаблоны, не являющиеся членами, которые невозможно с виртуальной диспетчеризацией (и функции, не входящие в функцию, помогают с симметричной перегрузкой оператора, например, поддерживают 22 + my_type
, а также my_type + 22
)
-
разные пространства имен могут указывать разные типы, которые будут использоваться для определенных целей (например, хеш-функция может возвращать 32-битное значение в одном пространстве имен, но 64-разрядное значение в другом), но виртуальный интерфейс должен иметь унификацию статические типы, что означает неуклюжее и высокое накладное косвенное отношение, например boost::any
или boost::variant
, или выбор наихудшего случая, когда биты высокого порядка иногда бессмысленны
-
виртуальная отправка часто включает в себя компромиссы между жировыми интерфейсами и неуклюжей обработкой ошибок: с пространством имён возможность просто не предоставлять функциональность в пространствах имен, где это не имеет смысла, обеспечивая принудительное выполнение необходимых усилий по переносу клиента
Ответ 3
Это поможет вам лучше понять.
например:
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)
Ответ 4
-
Не называют ли конфликты имен достаточной причиной? ADL-тонкости, особенно с перегрузками оператора, являются другими.
-
Это самый простой способ. Вы также можете использовать имена префиксов в пространстве имен, например. my_namespace:: name при определении.
Ответ 5
Вы можете рассматривать пространства имен как логически разделенные единицы для вашего приложения, а логические здесь означают, что предположим, что у нас есть два разных класса, поместив эти два класса в файл, но когда вы заметите, что эти классы делят что-то достаточно, чтобы быть категоризированным под одной категорией, является одной из сильных причин использования пространств имен.
Ответ 6
- Ответ. Если вы когда-нибудь захотите перегрузить новые, новые или удаленные функции размещения, которые вы захотите сделать в пространстве имен. Никто не хочет принуждать вас использовать вашу новую версию, если они не требуют того, что вам нужно.
- Да