Ответ 1
Я бы разместил их в анонимном пространстве имен в файле CPP. Это делает их закрытыми для реализации и в то же время делает видимыми функции, не являющиеся членами, которые являются частью реализации (например, operator<<
).
Мне нужно определить некоторые константные строки, которые будут использоваться только одним классом. Похоже, у меня есть три варианта:
Вставить строки непосредственно в места, где они используются.
Определите их как частные статические константные члены класса:
(После форматирования кода после ошибок перечислены ошибки.)
//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
(После форматирования кода после ошибок перечислены ошибки.)
//A.cpp
namespace {
const std::string f1 = "filename1";
const std::string f2 = "filename2";
const std::string f3 = "filename3";
}
//strings are used in this file
Учитывая эти варианты, которые вы бы порекомендовали и почему? Спасибо.
Я бы разместил их в анонимном пространстве имен в файле CPP. Это делает их закрытыми для реализации и в то же время делает видимыми функции, не являющиеся членами, которые являются частью реализации (например, operator<<
).
Если они используются только в одном файле, нет необходимости выставлять их во внешний мир, вставляя их в файл заголовка.
Если они используются и всегда будут использоваться только в одном месте, то нет причин не просто писать их как литералы, где они должны использоваться.
Если они используются в нескольких местах в cpp, я бы пошел на анонимное пространство имен.
Другой вариант, который вы не упоминаете, - это определить их как статические переменные внутри cpp. это несколько эквивалентно анонимному пространству имен и больше C-like, чем С++.
Статические члены класса.
Если они используются в нескольких местах одним классом, обычно проще организовать вещи - и позже найти, где вы определили все, - если вы сохраните их в классе, который их использует. Определение их на месте затрудняет их поиск и последующее изменение. И я бы выбрал конкретный класс над анонимным пространством имен для более чистого определения класса и использования.
Если строки предназначены для просмотра пользователями класса, поместите их в класс. В противном случае спрячьте их в пространстве имен без имени.
Если используется только в файле .cpp класса, нет необходимости использовать пространство имен любого типа, просто скажите:
const std::string f1 = "filename1";
const std::string f2 = "filename2";
const std::string f3 = "filename3";
Чрезмерное использование пространств имен, похоже, является новым - я не могу лично увидеть привлекательность.
Из трех вариантов единственное, что вы действительно должны избегать, это # 1. Не используйте в своем коде волшебные куки. Помещая константы либо в пространство имен, либо в класс, вы упростите расширение и поддержание своего кода в будущем.
Если ваши константы носят глобальный характер, то от 2 до 3 это имеет мало значения. Важно то, что вы выбираете его и придерживаетесь его. Но если у вас есть константы, которые применяются к определенному классу, то они должны быть частью этого класса.
Лично я бы использовал пространство имен для большинства вещей.
Я думаю, что реальная проблема заключается в следующем: строки действительно используются внутри только при реализации класса или используются в других местах.
Чтобы быть действительно придирчивым, я постараюсь максимально упростить интерфейс класса настолько, насколько это возможно, поэтому, если строки-имена не должны представлять интерес для "внешнего" мира. Я бы спрятал их внутри файла .cpp. И в этом случае я не думаю, что буду беспокоиться о пространстве имен, но просто сохраняю вещи "статическими" (т.е. Внутренними для .cpp файла).
Однако вы это делаете, нужно быть осторожным: я бы не рекомендовал использовать статические объекты std::string, вместо этого используйте static char *. Причина этого связана с потенциальными проблемами с порядком инициализации. Скажем, у вас есть статический экземпляр класса, конструктор которого ссылается на строку A::f1
. Нет никакой гарантии, что A::f1
был построен еще, и вы получите крах, или, что еще хуже, никаких сбоев, а фальшивых данных.
Отслеживание ошибок порядка-инициализации может быть довольно неприятным, и все может выглядеть хорошо в одном проекте, но тогда вы можете создать другой проект с использованием тех же библиотек, и тонкие различия в порядке ссылки вызовут эту ошибку загадочно появляются.
Просто иметь константные строки в области файлов в файле реализации, анонимное пространство имен не обязательно ограничивать их использование только этим классом.
С++ 003 Standard 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
Примечание. Анонимное пространство имен помогает уменьшить конфликты имен.