我有一个名称空间foo
,其中包含一个整数bar
,声明为......
foo.h中:
namespace foo {
int bar;
}
现在,如果我只在一个文件中包含foo.h
,那么这很好用。但是当我从两个或多个文件中包含foo.h
时出现问题:我收到链接器错误。我发现如果我将bar
声明为static
,我可以将foo.h
包含在多个文件中。这对我来说似乎很奇怪,因为我不知道可以在命名空间内声明一个静态变量。 (这甚至意味着什么?)
为什么这样做?更重要的是,为什么没有它没有 static
?在static
中使用namespace
时的含义是什么?
答案 0 :(得分:38)
static
在不同背景下有多种含义。在这个特定的上下文中,它意味着变量具有内部链接,因此包含该标题的每个翻译单元将拥有它自己的变量副本。
请注意,虽然这会使链接器错误无声,但它会为生成的每个目标文件维护一个单独的foo::bar
变量(不同目标文件之间不会显示更改)。
如果您想要一个变量,您应该在标题中将其声明为extern
,并在一个翻译单元中提供单个定义。
答案 1 :(得分:26)
当您将变量声明为static
时,表示其范围仅限于给定的翻译单元。没有static
,范围是全局的。
当你在.h文件中声明一个变量为static
时(在namespace
之内;无关紧要),并将该头文件包含在各种.cpp文件中,{{1变量变为本地范围到每个static
文件
所以现在,包含该标头的每个.cpp文件都有自己的变量副本。
如果没有.cpp
关键字,编译器将只生成该变量的一个副本,因此只要在多个.cpp文件中包含头文件,链接器就会抱怨多个定义。
答案 2 :(得分:4)
问题是由变量的多个定义引起的。不同翻译单元中的定义相互冲突,就像多个非内联函数定义不起作用一样。
当您将变量设为静态时,您将提供变量内部链接,因此每个翻译单元都有自己的独立副本。
您可能真正想要的是仅将声明放在标题中(使用extern),然后将定义放在实现文件中。
答案 3 :(得分:0)
还请注意,默认情况下,C ++的命名空间(全局)范围内的exports.A = class A { ... };
exports.b = 'constant';
已隐式添加了const int
:Define constant variables in C++ header
为了更好地了解发生了什么,请对编译的中间ELF目标文件执行static
,您将清楚地看到符号是否定义了两次。这是一个详细的示例:What does "static" mean in C?