Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 字符串的静态初始化顺序和串联_C++_String_String Concatenation_Static Initialization - Fatal编程技术网

C++ 字符串的静态初始化顺序和串联

C++ 字符串的静态初始化顺序和串联,c++,string,string-concatenation,static-initialization,C++,String,String Concatenation,Static Initialization,我们有一个相当大的项目,它在几个地方定义了static const std::strings作为参数名;其中一些需要在静态初始化期间连接: foo.h: struct Foo { static const std::string ParamSuffix; }; foo.cpp: const std::string Foo::ParamSuffix = ".suffix"; B.h: struct Bar { static const std::string ParamPrefix;

我们有一个相当大的项目,它在几个地方定义了
static const std::string
s作为参数名;其中一些需要在静态初始化期间连接:

foo.h:

struct Foo {
  static const std::string ParamSuffix;
};
foo.cpp:

const std::string Foo::ParamSuffix = ".suffix";
B.h:

struct Bar {
  static const std::string ParamPrefix;
};
bar.cpp:

const std::string Bar::ParamPrefix = "prefix";
baz.h:

struct Baz {
    static const std::string ParamName;
};
baz.cpp:

const std::string Baz::ParamName = Bar::ParamPrefix + Foo::ParamSuffix;
问题显然是“静态初始化失败”,因为没有定义
static const
成员初始化的顺序

我不喜欢通常的解决方案,即用函数替换所有这些变量,因为

  • 这些变量很多,也就是说,代码有很多变化
  • 串联需要特殊的函数,这使得代码基不一致,甚至更难看
  • 我目前不能使用C++11,因为它的
    constepr
    特性(我想)会让事情变得更简单


    问题是:有没有什么技巧可以让我连接
    静态常量std::string
    s(或包装器对象或任何东西)来初始化另一个
    静态常量std::string

    为什么你认为
    std::string const
    在任何方面都是特殊的?(提示:并非如此)即使您可以使用C++11的
    constexpr
    ,也不会有帮助,因为您无法生成
    std:string
    s常量表达式(它们可能需要分配内存,而内存不是可行的常量表达式)。您可以处理用于
    constexpr
    的类似字符串的类,该类可以转换为
    std::string
    ,但我不确定这些类是否可以连接起来生成新的
    constexpr

    您可能能够做的是提取那些您需要作为连接的一部分使用的字符串,并以宏的形式提供它们的值。字符串文字(对于合适的
    N
    ,其类型为
    char const[N]
    )可以通过简单地将它们相邻放置来连接:

    // foo.h
    #define FOO_PARAM_SUFFIX ".suffix"
    struct Foo {
        static const std::string ParamSuffix;
    };
    
    // foo.cpp:
    std::string const Foo::ParamSuffix(FOO_PARAM_SUFFIX);
    
    // bar.h:
    #define BAR_PARAM_SUFFIX "prefix"
    struct Bar {
        static std::string const ParamPrefix;
    };
    
    // bar.cpp:
    std::string const Bar::ParamPrefix(BAR_PARAM_SUFFIX);
    
    // baz.h:
    #include "foo.h"
    #include "bar.h"
    #define BAZ_PARAM_NAME BAR_PARAM_PREFIX FOO_PARAM_SUFFIX
    
    struct Baz {
        static std::string const ParamName;
    };
    
    // baz.cpp:
    #include "foo.h"
    #include "bar.h"
    std::string const Baz::ParamName(BAR_PARAM_PREFIX FOO_PARAM_SUFFIX);
    
    我猜,
    BAZ_PARAM_NAME
    没有在其他地方使用,在这种情况下,它也不需要定义:定义它只是为了表明它可以完成。
    Bar::ParamName
    的初始化假定未定义
    BAZ_PARAM_NAME

    问题是:有没有什么技巧可以让我连接static const std::string(或包装器对象或其他什么)来初始化另一个static const std::string

    除了你不喜欢的一个,没有什么琐碎的:为静态字符串创建函数

    但也有一些非常重要的替代方案(例如,用字符串容器/字符串映射替换所有硬编码字符串,并在应用程序启动时加载映射)


    我的建议是使用静态函数(您拒绝的解决方案)。< /P> < P>当文本不依赖于另一个变量时,您可以考虑将类型从“代码> const STD::String 改为<代码> const char < /COD>数组ALA <代码> const char PARAMP-前缀[]=“前缀”;<代码>-对客户端使用的强制更改可能较少,但这可能会隐藏每次使用时必须(或无意中)创建的新临时
    std::string
    s

    检查您的系统,但几乎可以肯定,您可以在构造其他
    std::string
    常量时安全地使用这些
    const char
    变量-但您的运气不好,因为它必然依赖于其他
    std::string
    s

    如果很难将现有值分解为只能依赖于
    const
    -
    char
    std::string
    s的can-be-
    const
    -
    char
    的can-be-
    const
    char,那么对每个常量的全面修改都是值得追求的

    包装器的吸引力在于可以保持使用的类型和语义相同。为此,您需要将所有这些运行时初始化字符串替换为您自己的类型,该类型协调两个中心列表:-初始化对象和等待对象。观察者模式是合适的,或者您可以注册回调列表并通过循环调用
    main()
    完成初始化,直到它们都指示成功:如果已知至少部分对象初始化是静态的,则允许一个对象测试另一个对象的初始化状态,这样可以避免让施工人员登记完工情况


    如果有更智能的源代码修改工具(如awk)的帮助,最好是简单地更改常量,使其干净地由函数返回。

    在使用宏之前,我仍然可以使用
    const char Foo::ParamSuffix[]=“.suffix”
    etc,并在连接到
    Baz::ParamName
    之前将其转换为
    std::string
    ,但我想要一个到处都是一致类型或至少隐藏丑陋的解决方案。@arne:你没有抓住重点。。。预处理器可以在源代码中一个接一个地放置带引号的字符串,然后编译器将它们连接起来形成一个新的字符串文字(即ASCIIZ C样式的字符串“常量”)。由于Dietmar在回答中提到的原因,您在编译时不能使用
    std::string
    s执行任何操作。@arne:
    const char x[]=“…”无法连接。我也不确定它们是否会足够早地初始化(即,在动态初始化之前或作为动态初始化的一部分)。这些对象很可能与
    std::string
    对象有相同的问题。@Dietmar:
    const char x[]
    解决方案在我们尝试时起作用了——字符串的内容被逐字放入可执行文件的只读部分。将它们转换为
    std::string
    (正如我前面提到的)并将它们连接起来(正如我前面提到的)效果非常好。“不过还是很难看。”@TonyD我知道预处理器可以做这样的事情。由于名称空间pol,我仍然觉得解决方案很难看