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

Why "int i" has multiple definitions?

我有两个文件如下:

Test1.h

#ifndef TEST_H
#define TEST_H

int i = 10;

#endif

Test2.cpp

#include <iostream>

#include "Test1.h"

int main()
{
    std::cout << i << std::endl;
}

我知道我可以通过在 Test1.h.

中使用 externconst 来解决这个问题

但我的问题是"I don't understand the error"。

error LNK2005: "int i" (?i@@3HA) already defined in Test1.obj
error LNK1169: one or more multiply defined symbols found

int i怎么可以有多个定义?

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

Test2.cpp

#include <iostream>

int i = 10

int main()
{
    std::cout << i << std::endl;
}

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

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

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

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

每个编译单元(一个 .cpp 文件)单独生成自己的一组符号,然后由链接器链接在一起。

一个header文件"becomes"它包含的编译单元的一部分,它编译成一个object文件(.obj in Windows,.o in Unix 系统)

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

Include guards 仅防止相同的 header 在同一个编译单元中被包含两次,如果我包含 and 并且其中一个包含另一个,则可能会发生这种情况。

When I include the header file it should mean that everything gets copied in Test2.cpp and it should become:

是的,然后您在 Test1.cpp 中执行完全相同的操作(您没有向我们展示)。

因此,多个定义。

How can int i have multiple definitions?

具有定义的文件包含在多个翻译单元(cpp 文件)中。一个单元被编译成 object 文件 Test1.obj。另一个单位的来源显示在您的答案中 (Test2.cpp)。当您尝试 link 将 object 个文件放在一起时会显示错误。

  1. The header file has include guards.

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

My other question is if I declare int i with extern in header file and include it in .cpp, then would it be an example of external linkage?

extern 明确地使 linkage 外部化。但即使没有 extern,在命名空间范围内声明的变量默认也有隐式外部 linkage(也有例外)。这种情况下的区别在于 extern 变量声明不是定义,除非有初始化程序。

I can achieve external linkage without including header file i.e. with two .cpp files by making a variable extern in one .cpp and defining it in other and linker finds its definition. But if I have one header file with extern variable and include it in other .cpp does this count as external linkage?

外部声明如何在 cpp 文件中结束并不重要。无论它是否包含在 header 中,它都声明了一个具有外部 linkage.

的变量

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

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

原因可以是以上两个问题之一的答案。