【问题标题】:C++ Class Common String ConstantsC++ 类通用字符串常量
【发布时间】:2010-11-01 01:35:25
【问题描述】:

在 C++ 中,我想定义一些将在类中使用的字符串,但这些值将在所有实例中通用。在 C 语言中,我会使用 #defines。这是一个尝试:

#include <string>
class AskBase {
public:
    AskBase(){}
private:
    static std::string const c_REQ_ROOT = "^Z";
    static std::string const c_REQ_PREVIOUS = "^";
    static std::string const c_REQ_VERSION = "?v";
    static std::string const c_REQ_HELP = "?";
    static std::string const c_HELP_MSG = "  ? - Help\n ?v - Version\n ^^ - Root\n  ^ - Previous\n ^Z - Exit";
};
int main(){AskBase a,b;}

如果需要 C++0x 是可以接受的。

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    您必须在单个翻译单元(源文件)中分别定义它们,如下所示:

    //header
    class SomeClass
    {
      static const std::string someString;
    };
    
    //source
    const std::string SomeClass::someString = "value";
    

    我相信新的 C++1x 标准会解决这个问题,尽管我不完全确定。

    【讨论】:

    • 请注意,这是您必须初始化任何非内置类型(例如 int、bool、double 等)的静态成员的方式。
    • 我听说他们目前正在审查它:目前的情况是,您只能使用整数常量表达式直接初始化类内文字类型(文字类型有 constexpr ctor 之类的东西 - 所以,没有std::string) - 涉及静态数据成员。不过,您可以直接在类中初始化任意非静态成员,并且初始化也可能有副作用。
    【解决方案2】:

    我永远不会使用那种结构。
    如果其中一位开发人员重构代码并开始编写:

       // header
       class StringBug
       {
            static const std::string partOfTheString;
            static const std::string wholeString;
       };
    
       // source
       const std::string StringBug::partOfTheString = "Begin ";
       const std::string StringBug::wholeString = partOfTheString + "and the rest";
    

    您很难在程序中找到错误,因为没有保证 partOfTheString 在用于创建 WholeString 之前已初始化;

    如果我想创建类公共字符串,我会这样做:

    // header
    class StringBug
    {
        static const std::string& partOfTheString() {
           static const std::string sPartOfTheString("Begin ");
           return sPartOfTheString;      
        }
    
        static const std::string& wholeString() {
           static const std::string sWholeString( partOfTheString() + "and the rest");
           return sWholeString;
        }
    };
    

    【讨论】:

    • 糟糕的表现!一种获取静态编译时已知字符串的方法调用!
    • 大多数时候它与性能无关,而是与代码安全有关。有一些编码约定将此结构包含在指南中,只有当您可以证明性能部分的合理性时,您才能忽略该指南。
    • 性能?这些是在标题中定义的,因此将被隐式内联。
    【解决方案3】:

    根据Wikipedia article,这应该在C++0x 中得到支持,但是我在State of C++ Evolution 页面中找不到参考。

    【讨论】:

      【解决方案4】:

      当我需要一个类中的字符串常量时,我​​从不将它们放在类本身中,但是:

      1) 如果它们需要在标头中公开,我将它们放在类之外(如果合适,放在命名空间中),如下所示:

      const char * const c_REQ_ROOT = "^Z";
      ...
      

      2) 如果没有,我将它们放在 cpp 文件中,在匿名命名空间中。

      您甚至可以将来自多个相关组件的字符串常量分组到同一个头文件中。

      这可能不是最“学术”的方式,但代码更简单,更容易重构。我从未发现将字符串常量定义为静态类成员的任何实际优势。

      我对这里其他程序员的意见很感兴趣,所以不要犹豫离开你的 cmets。

      【讨论】:

      • 我同意,因为它们是私有的,我会将它们放在 cpp 文件中的匿名命名空间中,并将它们放在标题之外,然后对常量结构的更改不会强制重新编译客户端代码。
      猜你喜欢
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 2020-05-01
      • 2012-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      相关资源
      最近更新 更多