为什么 Visual Studio 给出重复错误,即使我没有明确包含源文件?

Why is Visual Studio giving a duplicate error even though I'm not explicitly including a source file?

我正在使用 Visual Studio 2019。我创建了一个新的 C++ 控制台应用程序。我的源文件文件夹中有一个文件 Main.cpp,代码如下:

#include <iostream>

int i = 10;

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

我在名为 File2.cpp 的源文件文件夹中创建了第二个文件,其中只有以下行:

int i = 2;

如果我尝试编译这段代码,我会得到一个错误 "one or more multiply defined symbols found"。为什么我没有在 Main.cpp 中明确地完成 #include "File2.cpp"

更新: 但是,如果我删除 File2.cpp 并将其替换为我的头文件文件夹中名为 File2.h 的文件(仅包含一行: int i = 2), 并且所有其他条件都相同,它编译得很好。与前面的示例类似,唯一的区别是第二个文件不是 .cpp 源文件,而是现在是 .h 头文件。

首先,您永远不想包含 cpp 文件。构造代码的一般方法1 是将声明放在一个或多个头文件中,然后为每个头文件创建一个 cpp 文件。然后编译 link 所有这些 cpp 文件。

这是 Visual Studio 自动为您做的。您在项目中创建所有头文件和 cpp 文件,然后它将编译每个 cpp 文件,然后 link 生成的目标文件一起构建可执行文件。因此,因为 Main.cppFile2.cpp 都定义了相同的变量,所以会出现多重定义错误,因为这两个文件是一起编译的。

1: unless you have templates

在 C++ 中,全局变量(在任何 class 之外声明)默认具有外部链接。也就是说,当应用程序被链接时,它们对其他模块是可见的。

因此,两个 .cpp 文件都向链接器公开了一个变量 i,该对象是对象。

四种解决方案:

1) 将一个或两个声明放在不同的名称空间中:

namespace Wibble
{
    int i = 2;
}

因此它们具有不同的完全限定名称。

2) 将一个或两个声明为 static:

static int i = 2;

关闭外部链接。

3) 将一个或两个放在匿名命名空间中:

namespace
{
    int i = 2;
}

自动为每个命名空间分配一个唯一的命名空间 - 实际上与 (2)

相同的结果

4) 声明除了其中一个之外的所有都为 extern 没有初始化:

extern int i;

这表示变量 i 实际上与另一个文件中的变量是同一个变量,它没有被声明为 extern.