Куда я помещаю постоянные строки в C++: статические члены класса или анонимные пространства имен?

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

  1. Вставляйте строки прямо в места, где они используются.

  2. Определите их как частные статические постоянные члены класса:

    //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  
    
  3. Определите их в анонимном пространстве имен в файле 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

Примечание. Анонимное пространство имен помогает уменьшить конфликты имен.

Другие вопросы по тегам