LNK1169由于在单独的 cpp 文件中多次包含标头而导致的

LNK1169 caused by including a header more than once in separate cpp files

提问人:Indica 提问时间:3/13/2023 最后编辑:JabberwockyIndica 更新时间:3/14/2023 访问量:98

问:

在我的程序中,我遇到了LNK1169,考虑到上下文,我看不出这个错误是如何导致的。

单位.h:

#ifndef UNITS_H
#define UNITS_H

namespace units {
    extern constexpr double N = 1.0;
};

#endif

答:

#pragma once
class A {
public:
    A();
};

.cpp:

#include "A.h"
#include "units.h"

A::A() {

}

B.h:

#pragma once
class B {
public:
    B();
};

B.cpp:

#include "B.h"
#include "units.h"

B::B() {

}

错误测试.cpp:

#include "A.h"
#include "B.h"

int main()
{
    A* _a = new A();
    B* _b = new B();
    return 0;
}

错误消息:

Error   LNK1169 one or more multiply defined symbols found  ErrorTest   C:\Users\---\source\repos\ErrorTest\x64\Debug\ErrorTest.exe 1
Error   LNK2005 "double const units::N" (?N@units@@3NB) already defined in A.obj    ErrorTest   C:\Users\---\source\repos\ErrorTest\ErrorTest\B.obj 1

我是否遗漏了什么显而易见的东西?我确信我遵守一个定义规则。

我试图确保我遵循一个定义规则并更改我包含 units.h 的方式,但错误始终相同。如果我在多个 cpp 中包含 units.h,我总是会得到LNK1169。

C++ 编译 包括 链接器错误

评论

0赞 Jabberwocky 3/13/2023
你展示的一切都很好。你的项目一定有问题,或者你没有展示的其他东西。
0赞 Some programmer dude 3/13/2023
删除 in 如果您在 C++17(或更高版本)模式下构建,则替换为 .externextern constexpr double N = 1.0;externinline
1赞 Indica 3/13/2023
@Jabberwocky 这很奇怪。上面的代码是用一个全新的项目制作的。如果配置错误是没有意义的。
1赞 Jabberwocky 3/13/2023
@Someprogrammerdude Visual Studio 2022,适用于 x86 的 MS 编译器 19.30.30706,链接器 14.30.30706.0。使用 c++20.
1赞 Some programmer dude 3/13/2023
因为你添加了关键字,所以定义将具有外部链接。这将导致在包含头文件的所有翻译单元中定义变量。如果删除关键字,它将具有内部链接(因为)。或者,不要在头文件中定义变量,只声明它(保留但删除初始化,将定义(没有但有初始化)放在单个源文件中)。externexternconstexprexternextern

答:

0赞 Teeeeeeeeeeeeeeeeeeeeeeeeeeeej 3/14/2023 #1

我认为这是因为当你编译时,你会得到定义为包含的一部分的units::N。a.cpp

然后,当您编译 时,您还将获得定义为包含的一部分的 units::N。包含保护仅适用于预处理阶段,但此时您已经编译了 a.cpp 和 b.cpp,两者都包含 units.h。由于您在两者中都定义了(而不是声明的)N,因此链接器可能将其视为错误。b.cpp

如果你想阅读更多关于它的信息,并且由于它看起来你正在使用 VS,这里有一个文档链接,并且有具体的提及。https://learn.microsoft.com/en-us/cpp/cpp/extern-cpp?view=msvc-170externextern constexpr

0赞 user12002570 3/14/2023 #2

问题是,这是一个以外部链接命名的变量的定义,因为你使用了关键字。因此,当这个头文件被多个源文件包含时,该变量会被多次定义,因此会出现错误。extern constexpr double N = 1.0;Nextern

解决此问题,请删除关键字,以便具有内部链接,或者如果您使用的是 c++17,则将其替换为。externNexterninline