为什么"int i"有多个定义?

Why "int i" has multiple definitions?

本文关键字:定义 int 为什么      更新时间:2023-10-16

我有两个文件如下:

测试1.h

#ifndef TEST_H
#define TEST_H
int i = 10;
#endif

测试2.cpp

#include <iostream>
#include "Test1.h"
int main()
{
    std::cout << i << std::endl;
}

我知道我可以通过在 Test1.h 中使用 externconst 来解决这个问题。

但我的问题是"我不明白错误"。

错误 LNK2005:"int i"(?i@@3HA)已在 Test1.obj
中定义 错误 LNK1169:找到一个或多个乘法定义的符号

int i如何有多个定义?

  1. 头文件具有包含保护。
  2. 当我包含头文件时,它应该意味着所有内容都被复制到Test2.cpp中,它应该变成:

测试2.cpp

#include <iostream>
int i = 10
int main()
{
    std::cout << i << std::endl;
}

在包含所有内容后,头文件此时应该变得无关紧要。

我的另一个问题是,如果我在头文件中声明带有externint i并将其包含在.cpp中,那么它会是外部链接的一个例子吗?因为通常我已经看到两个.c.cpp之间的外部链接,就像这里一样,但是如果您明确包含该文件,它是否仍然被视为具有外部链接i

每个编译单元(.cpp文件)单独生成自己的符号集,然后通过链接器将这些符号链接在一起。

头文件"成为"它所包含的编译单元的一部分,编译为目标文件(Windows中的.obj,Unix系统中的.o)

因此,就像您在每个编译单元中定义了一个全局"i"。正确的解决方案(如您所知,如果您必须有一个全局)是在标头中将其声明为"extern",然后让一个编译单元实际定义它。

包含

保护只能防止同一标头在同一编译单元中包含两次,如果我包含并且其中一个包含另一个,则可能会发生这种情况。

int i 怎么能有多个定义?

具有定义的文件包含在多个翻译单元(cpp 文件)中。一个单元被编译到目标文件Test1.obj 中。另一个单元的来源显示在您的答案中(Test2.cpp)。当您尝试将目标文件链接在一起时,将显示此错误。

  1. 头文件具有包含保护。

这可以防止文件的内容在单个翻译单元中重复。分开单位没有区别。

我的另一个问题是,如果我在头文件中使用 extern 声明 int i 并将其包含在.cpp中,那么它会是外部链接的一个例子吗?

extern使链接显式外部。但即使没有extern,在命名空间作用域中声明的变量也默认具有隐式的外部链接(也有例外)。这种情况的区别在于,除非存在初始值设定项,否则extern变量声明不是定义。

我可以在不包含头文件的情况下实现外部链接,即通过在一个.cpp中创建一个变量 extern 并在另一个中定义它来实现两个.cpp文件,链接器找到它的定义。但是,如果我有一个带有 extern 变量的头文件并将其包含在其他.cpp这算不算外部链接?

外部声明如何最终出现在 cpp 文件中并不重要。无论它是否包含在标头中,它都会声明一个具有外部链接的变量。

可能您正在尝试从两个翻译单元创建可执行文件。

您的错误表明该对象已在 Test1.obj 中定义。可能,你的程序是Test1.obj+Test2.obj,两个文件包含相同的定义,具有外部链接。

您的项目中还有其他 Test1.cpp 也包含 Test1.h 吗?

如果没有,您是否对编译器进行任何配置,以便它也将 .h 文件构建为目标文件?

原因可能只是上述两个问题之一的答案。

当我包含头文件时,它应该意味着所有内容都被复制到 Test2 中.cpp它应该变成:

是的,然后你在 Test1 中做了完全相同的事情.cpp(你没有向我们展示)。

因此,多个定义。