Куда я помещаю постоянные строки в C++: статические члены класса или анонимные пространства имен?
Мне нужно определить несколько константных строк, которые будут использоваться только одним классом. Похоже, у меня есть три варианта:
Вставляйте строки прямо в места, где они используются.
Определите их как частные статические постоянные члены класса:
//A.h class A { private: static const std::string f1; static const std::string f2; static const std::string f3; }; //A.cpp const std::string f1 = "filename1"; const std::string f2 = "filename2"; const std::string f3 = "filename3"; //strings are used in this file
Определите их в анонимном пространстве имен в файле cpp:
//A.cpp namespace { const std::string f1 = "filename1"; const std::string f2 = "filename2"; const std::string f3 = "filename3"; } //strings are used in this file
Учитывая эти варианты, какой из них вы бы порекомендовали и почему? Благодарю.
9 ответов
Я бы поместил их в анонимное пространство имен в файле CPP. Это делает их приватными для реализации и в то же время делает их видимыми для не-членских функций, которые являются частью реализации (таких как operator<<
).
Если они используются только в одном файле, то нет необходимости показывать их внешнему миру, включая их в заголовочный файл.
Если они используются и всегда будут использоваться только в одном месте, то на самом деле нет причин не просто записывать их как литералы, где их нужно использовать.
Если бы они использовались в нескольких местах в cpp, я бы выбрал анонимное пространство имен.
Другой вариант, который вы не упомянули - это определить их как статические переменные внутри cpp. это несколько эквивалентно опции анонимного пространства имен и более похоже на C, чем на C++.
Статические члены класса.
Если они используются в нескольких местах одним классом, обычно легче упорядочить вещи - и позже найти, где вы все определили - если вы оставите их определенными в классе, который их использует. Определение их на месте затрудняет их поиск и последующее изменение. И я бы выбрал конкретный класс для анонимного пространства имен для более чистого определения и использования класса.
Если строки предназначены для просмотра пользователями класса, поместите их в класс. В противном случае скройте их в безымянном пространстве имен файла реализации.
Если используется только в файле класса.cpp, нет необходимости использовать какое-либо пространство имен, просто скажите:
const std::string f1 = "filename1";
const std::string f2 = "filename2";
const std::string f3 = "filename3";
Чрезмерное использование пространств имен, кажется, новая вещь - я лично не вижу привлекательности.
Я думаю, что реальная проблема заключается в следующем: действительно ли строки используются только для реализации класса, или они используются где-то еще.
Чтобы быть действительно придирчивым, я бы постарался сохранить интерфейс класса настолько чистым, насколько это возможно, поэтому, если строки имени файла не должны представлять интереса для "внешнего" мира. Я бы скрыл их внутри только в.cpp-файле. И в этом случае я не думаю, что буду беспокоиться о пространстве имен, а просто сохраню "статичность" (то есть внутреннюю по отношению к.cpp-файлу).
Тем не менее, вы делаете это, но с одной вещью нужно быть осторожным: я бы не рекомендовал использовать статические объекты std::string, вместо этого используйте static char*. Причина этого связана с потенциальными проблемами с порядком инициализации. Допустим, у вас есть статический экземпляр класса, конструктор которого ссылается на строку A::f1
, Там нет никакой гарантии, что A::f1
был построен еще, и вы получите крах, или, что еще хуже, не крах, но поддельные данные.
Отслеживание ошибок порядка инициализации может быть довольно неприятным, и все может выглядеть хорошо в одном проекте, но тогда вы можете построить другой проект, используя те же библиотеки, и небольшие различия в порядке ссылок приведут к таинственному появлению этой ошибки.
Из трех возможных вариантов следует избегать только одного. Не используйте магические куки в вашем коде. Поместив константы в пространство имен или в класс, вы упростите расширение и поддержку своего кода в будущем.
Если ваши константы имеют глобальный характер, то между 2 и 3 это мало что значит. Важно то, что вы выбираете один и придерживаетесь его. Но если у вас есть константы, которые применяются к определенному классу, то они должны быть частью этого класса.
Лично я бы использовал пространство имен для большинства вещей.
Просто поместите строки const в область действия файла в файле реализации, анонимное пространство имен не обязательно ограничивать их использование только этим классом.
Стандарт C++ 003 C.1.2, пункт 3: основные понятия
Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage
Примечание. Анонимное пространство имен помогает уменьшить конфликты имен.