之前
const char * const g_someString = "Hello";
你需要将其声明为extern
(例如通过包括头部),因为const
命名空间层次变量的缺省内部链接。
也就是说,你可以在标题中定义字符串。单独的编译让您可以修改字符串而不会重建大量文件,但除此之外,恕我直言,这是过早的优化。
为了使字符串定义在头正式安全的inline
功能,如果这是需要的,你需要的字符串(或至少是指针)有extern
联动。一种方法是在一个定义规则中利用特殊的模板豁免。例如。像这样:
// Perhaps best generated by some code generation facility:
template< class Dummy >
struct Strings_
{
static char const* const some_string;
static char const* const some_other_string;
};
template< class Dummy >
char const* const Strings_<Dummy>::some_string = "Blah!";
template< class Dummy >
char const* const Strings_<Dummy>::some_string = "Oh, well.";
using Strings = Strings_<void>;
然后使用像
inline void foo() { cout << Strings::some_string << endl; }
这里Strings::some_string
指针会在所有的翻译单位相同。
另一种方法是定义inline
函数中的字符串。然后你可以使用例如枚举来命名它们。
enum String_id { some_string, some_other_string };
inline
auto strings(String_id const id)
-> char const*
{
switch(id)
{
case some_string: return "Blah!";
case some_other_string: return "Oh, well.";
}
assert(false); // Should never get here.
}
与使用像
inline void foo() { cout << strings(some_string) << endl; }
的inline
功能有extern
联动,因此它在所有的翻译单位相同。
在_constants.cpp_ – Karthik
中的定义确保'constants.cpp'包含'constants.h'(并且没有循环依赖关系) –
'void main'的定义之前,链接器错误消失了_extern_声明在C++中是非法的,即使你的编译器提供了一个不合规的扩展名,编写依赖于这些扩展名的代码也是不好的 –