Превосходство безымянного пространства имен над статическим?


130

Чем безымянные пространства имен превосходят staticключевое слово?


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

Ответы:


134

Вы в основном имеете в виду раздел §7.3.1.1 / 2 стандарта C ++ 03,

Использование ключевого слова static не рекомендуется при объявлении объектов в области пространства имен; безымянное пространство имен обеспечивает превосходную альтернативу.

Обратите внимание, что этот абзац уже был удален в C ++ 11. стандартные функции больше не staticсчитаются устаревшими!

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

Следующий код действителен в C ++

   //legal code
   static int sample_function() { /* function body */ }
   static int sample_variable;

Но этот код НЕ действителен:

   //illegal code
   static class sample_class { /* class body */ };
   static struct sample_struct { /* struct body */ };

Итак, решение - безымянное пространство имен, то есть

   //legal code
   namespace 
   {  
        class sample_class { /* class body */ };
        struct sample_struct { /* struct body */ };
   }

Надеюсь, это объясняет, почему unnamed-namespaceлучше static.

Также обратите внимание, что использование ключевого слова static устарело при объявлении объектов в области пространства имен (согласно Стандарту).


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

10
Как отметил Фред Нурк в другом вашем ответе, похоже, что это deprecatedзамечание было удалено из последней версии C ++ 0x FCD (n3225).
Matthieu M.

36
Вы отвечаете на свой вопрос и благодарите себя: -o
manpreet singh

12
В чем будет разница от простого определения класса в cpp (без анонимного пространства имен, без статики)?
Лучиан Григоре

6
@LuchianGrigore Проблемы со связью в случае 2 .cppсвязаны с определением класса с тем же именем.
Xaqq 03

8

С этим связана интересная проблема:

Предположим, вы используете static ключевое слово или безымянный, namespaceчтобы сделать некоторую функцию внутренней по отношению к модулю (единицей перевода), поскольку эта функция предназначена для внутреннего использования модулем и недоступна вне его. (Безымянный namespaces имеет то преимущество, что делает данные и определения типов также внутренними, помимо функций).

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

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

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

Было бы замечательно, если бы можно было указать, что some namespaceis private, то есть все, что в нем определено, предназначено для внутреннего использования модулем, которому он принадлежит. Но, конечно, в C ++ нет понятия «модули», только «единицы перевода», которые жестко привязаны к исходным файлам.


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

не использует ли наследование с частным / защищенным / общедоступным со статическими функциями решения?
Али

C ++ 20 вводит модули, которые решают вашу проблему.
LF
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.