我有一个命名空间foo
其中包含一个整数bar
,宣告所以...
foo.h中:
namespace foo {
int bar;
}
现在,如果我包括foo.h
中只有一个文件,这个工作得很好。 但是,当我有一个问题出现foo.h
我得到一个链接错误:从两个或多个文件。 我想通了,如果我声明bar
为static
,我可以包括foo.h
的多个文件。 这似乎很奇怪,我,因为我不知道,人们可以声明命名空间内的静态变量。 (那有什么意思?)
为什么这项工作? 更重要的是,为何它没有工作没有 static
? 什么static
在使用时平均namespace
?
有多重含义static
在不同的上下文。 在此特定情况下它意味着该变量具有内部连接,因此,其包括头部将有它的可变的自己的副本每个翻译单元。
请注意,虽然这无声的链接错误,它会做这样保持一个独立的foo::bar
为生成的目标文件中的每一个(变化将不会在不同的目标文件可见)变量。
如果你想要一个变量,你应该把它声明为extern
在头,并提供一个转换单元的单一定义。
当一个变量声明为static
,这意味着其范围仅限于给定的翻译单元 。 如果没有static
的范围是全球性的。
当一个变量声明为static
.h文件内(在有或没有namespace
;无所谓),并且包括在不同的.cpp文件头文件中, static
变量变成局部范围到每一个的.cpp
文件。
所以,现在,这包括每头.cpp文件都会有自己该变量的副本。
如果没有static
关键字,编译器将生成唯一一个变量的副本,因此只要您在多个的.cpp头文件中的文件,链接器将抱怨多重定义。
该问题通过具有可变的多个定义而引起的。 在相互不同的翻译单位冲突的定义,就像多个非内联函数定义是行不通的。
当你让你给变量内部连接的静态变量,因此每个翻译单元都有自己独立的副本。
你可能实际上要的是只放声明在一个头(使用EXTERN),然后把定义在实现文件。
还要注意的是const int
在C ++已经命名空间(全局)范围static
隐含默认添加: 在C ++头定义常量变量
为了更好地理解正在发生的事情,做一个readelf
在编译的中间ELF对象文件,你会看到两次或没有明确的定义符号。 这里是一个详细的例子: 什么是“静态”的意思是用C?