如果我有防护装置,为什么会发生这种情况?我认为他们在第一次访问后阻止了标头被读入。
包含守卫确保标题在一个文件(翻译单元)中只包含一次。对于包括标头的多个文件,您希望标头包含在每个文件中。
通过定义,而不是在头文件中声明具有外部链接的变量(全局变量),您只能在一次源文件中包含头文件。如果在多个源文件中包含头文件,则会有多个变量定义,这在 C++ 中是不允许的。
因此,正如您所发现的,正是出于上述原因,在头文件中定义变量是一个坏主意。
为什么此标头中的众多枚举也没有给出 LNK4006 警告?
因为,它们没有定义“全局变量”,它们只是关于类型的声明等。它们不保留任何存储空间。
如果我在签名之前添加静态,我不会收到警告。这样做有什么影响。
当您创建一个变量static
时,它具有静态范围。该对象在定义它的翻译单元(文件)之外不可见。所以,简单来说,如果你有:
static int i;
在您的标头中,包含标头的每个源文件都将获得一个单独 int
的变量i
,该变量在源文件之外是不可见的。这称为内部链接。
有没有更好的方法来避免错误,但让我在标题中声明数组。我真的很讨厌只为数组定义创建一个 cpp 文件。
如果您希望数组成为所有 C++ 文件中可见的一个对象,您应该这样做:
extern int array[SIZE];
在您的头文件中,然后将头文件包含在所有需要该变量的 C++ 源文件中array
。在其中一个源 ( .cpp
) 文件中,您需要定义array
:
int array[SIZE];
您还应该在上述源文件中包含标头,以便发现由于标头和源文件的差异而导致的错误。
基本上,extern
告诉编译器“array
在某处定义,并且具有 typeint
和 size SIZE
”。然后,您实际上只定义 array
了一次。在链接阶段,一切都很好地解决了。