静态VS在命名空间的非静态变量

静态VS在命名空间的非静态变量

问题描述:

我有一个命名空间foo其中包含一个整数bar,宣布所以...静态VS在命名空间的非静态变量

了foo.h:

namespace foo { 
    int bar; 
} 

现在,如果我有foo.h只有一个文件,这工作得很好。但是当我从两个或多个文件中包含foo.h时出现问题:出现连接器错误。我发现如果我宣布barstatic,我可以在一个以上的文件中包含foo.h。这对我来说似乎很陌生,因为我不知道可以在名称空间内声明一个静态变量。 (这是什么意思?)

这是为什么?更重要的是,为什么不是它的工作没有static?当在namespace中使用时,static是什么意思?

+0

Upvote。是我的问题,并解决它:) – 2014-07-01 17:12:18

static在不同的环境中有多种含义。在这个特定的上下文中,这意味着变量具有内部链接,因此包含该头文件的每个翻译单元都将拥有自己的变量副本。

请注意,尽管这样可以避免链接器错误,但它将为每个生成的对象文件(在不同的对象文件间都无法看到更改)保留单独的foo::bar变量。

如果你想要一个变量,你应该在头文件中声明它为extern,并在一个翻译单元中提供一个单一的定义。

当您声明一个变量为static时,这意味着它的范围仅限于给定的翻译单元。没有static范围是全球性的。

当一个变量声明为static .h文件(在或不在namespace;无所谓)内,并且包括在不同的cpp文件该头文件中,变量static变得局部范围到每个.cpp的文件。
所以现在,包含该头文件的每个.cpp文件都将拥有自己的该变量副本。

如果没有static关键字,编译器将只生成该变量的一个副本,因此只要将头文件包含在多个.cpp文件中,链接器就会抱怨多个定义。

该问题是由变量的多个定义引起的。不同翻译单元中的定义相互冲突,就像多个非内联函数定义不起作用。

当您将变量设置为静态时,您会给出可变的内部链接,因此每个翻译单元都有自己的独立副本。

你可能真正想要的只是将声明放在一个头文件中(使用extern),然后将该定义放在一个实现文件中。