C++ 错误 LNK2005,已定义?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10046485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:32:43  来源:igfitidea点击:

error LNK2005, already defined?

c++

提问by TTGroup

I have 2 files, A.cpp and B.cpp, in a Win32 console application.

我在 Win32 控制台应用程序中有 2 个文件,A.cpp 和 B.cpp。

Both 2 files contain only the following 2 lines of code:

这两个文件都只包含以下两行代码:

#include "stdafx.h"
int k;

When compiling it produces the error

编译时会产生错误

Error   1   error LNK2005: "int k" (?a@@3HA) already defined in A.obj

I don't understand what is happening.

我不明白发生了什么。

Can someone please explain this to me?

有人可以向我解释一下吗?

回答by Alok Save

Why this error?

为什么会出现这个错误?

You broke the one definition ruleand hence the linking error.

您违反了一个定义规则,因此出现了链接错误。

Suggested Solutions:

建议的解决方案:



If you need the same named variable in the two cpp files then You need to use Nameless namespace(Anonymous Namespace) to avoid the error.

如果您需要在两个 cpp 文件中使用相同的命名变量,那么您需要使用 Nameless namespace(Anonymous Namespace) 来避免错误。

namespace 
{
    int k;
}


If you need to share the same variable across multiple files then you need to use extern.

如果您需要在多个文件之间共享相同的变量,那么您需要使用extern.

A.h

extern int k;

A.cpp

A.cpp

#include "A.h"
int k = 0;

B.cpp

B.cpp

#include "A.h"

//Use `k` anywhere in the file 

回答by Michael Haephrati

In the Project's Settings, add /FORCE:MULTIPLEto the Linker's Command Lineoptions.

在项目的设置中,添加 /FORCE:MULTIPLE到链接器的命令行选项。

From MSDN: "Use /FORCE:MULTIPLE to create an output file whether or not LINK finds more than one definition for a symbol."

来自MSDN:“无论 LINK 是否为一个符号找到多个定义,都使用 /FORCE:MULTIPLE 创建输出文件。”

回答by Jerry Coffin

If you want both to reference the same variable, one of them should have int k;, and the other should have extern int k;

如果您希望两者都引用同一个变量,则其中一个应该有int k;,另一个应该有extern int k;

For this situation, you typically put the definition (int k;) in one .cppfile, and put the declaration (extern int k;) in a header, to be included wherever you need access to that variable.

对于这种情况,您通常将定义 ( int k;) 放在一个.cpp文件中,并将声明 ( extern int k;) 放在头文件中,以便在需要访问该变量的任何地方包含该文件。

If you want each kto be a separate variable that just happen to have the same name, you can either mark them as static, like: static int k;(in all files, or at least all but one file). Alternatively, you can us an anonymous namespace:

如果您希望每个k变量都是碰巧具有相同名称的单独变量,您可以将它们标记为static,例如:(static int k;在所有文件中,或至少除了一个文件之外的所有文件)。或者,您可以使用匿名命名空间:

namespace { 
   int k;
};

Again, in all but at most one of the files.

同样,在所有文件中,但最多只有一个文件。

In C, the compiler generally isn't quite so picky about this. Specifically, C has a concept of a "tentative definition", so if you have something like int k;twice (in either the same or separate source files) each will be treated as a tentative definition, and there won't be a conflict between them. This can be a bit confusing, however, because you still can't have two definitions that both include initializers--a definition with an initializer is always a full definition, not a tentative definition. In other words, int k = 1;appearing twice would be an error, but int k;in one place and int k = 1;in another would not. In this case, the int k;would be treated as a tentative definition and the int k = 1;as a definition (and both refer to the same variable).

在 C 中,编译器通常对此不太挑剔。具体来说,C 有一个“暂定定义”的概念,所以如果你有int k;两次(在相同或不同的源文件中),每一个都将被视为暂定定义,它们之间不会有冲突。然而,这可能有点令人困惑,因为您仍然不能有两个都包含初始化器的定义——带有初始化器的定义始终是完整定义,而不是暂定定义。换句话说,int k = 1;出现两次是错误的,但int k;在一个地方和int k = 1;另一个地方不会。在这种情况下, theint k;将被视为暂定定义,而 the将被视为int k = 1;定义(并且两者都引用相同的变量)。

回答by abelenky

Both files define variable kas an integer (int).

这两个文件都将变量定义k为整数 ( int)。

As a result, the linker sees two variables with the same name, and is unsure which one it should use if you ever refer to k.

结果,链接器看到两个具有相同名称的变量,如果您曾经引用k.

To fix this, change oneof the declarations to:

要解决此问题,请将其中一项声明更改为:

extern int k;

That means: "k is an integer, declared here, but defined externally (ie. the other file)."

这意味着:“k 是一个整数,在此处声明,但在外部定义(即另一个文件)。”

Now there is only one variable k, that can be properly referred to by two different files.

现在只有一个变量k,可以被两个不同的文件正确引用。

回答by Steve Howard

Assuming you want 'k' to be a different value in different .cpp files (hence declaring it twice), try changing both files to

假设您希望 'k' 在不同的 .cpp 文件中成为不同的值(因此声明两次),请尝试将两个文件更改为

namespace {
    int k;
}

This guarantees that the name 'k' uniquely identifies 'k' across translation units. The old version static int k;is deprecated.

这保证了名称“k”在翻译单元中唯一标识“k”。旧版本static int k;已弃用。

If you want them to point to the same value, change one to extern int k;.

如果您希望它们指向相同的值,请将其更改为extern int k;

回答by arrowd

And if you want these translation units to share this variable, define int k;in A.cpp and put extern int k;in B.cpp.

如果您希望这些翻译单元共享此变量,请int k;在 A.cpp 中定义并放入extern int k;B.cpp。

回答by user7860670

Presence of int k;in the header file causes symbol kto be defined within each translation unit this header is included to while linker expects it to be defined only once (aka One Definition Rule Violation).

的存在int k;在头文件使符号k到每个转换单元这个头被包括以同时接头期望它仅进行一次(又名一个定义规则违例)所定义范围内来限定。

While suggestion involving externare not wrong, externis a C-ism and should not be used.

虽然涉及extern的建议没有错,但它extern是一种 C 主义,不应使用。

Pre C++17 solution that would allow variable in header file to be defined in multiple translation units without causing ODR violation would be conversion to template:

允许在多个翻译单元中定义头文件中的变量而不导致 ODR 违规的 C++17 之前的解决方案将转换为模板:

template<typename x_Dummy = void> class
t_HeaderVariableHolder
{
    public: static int s_k;
};

template<typename x_Dummy> int t_HeaderVariableHolder<x_Dummy>::s_k{};

// Getter is necessary to decouple variable storage implementation details from access to it.
inline int & Get_K() noexcept
{
    return t_HeaderVariableHolder<>::s_k;
}

With C++17 things become much simpler as it allows inlinevariables:

使用 C++17,事情变得更简单,因为它允许inline变量:

inline int g_k{};

// Getter is necessary to decouple variable storage implementation details from access to it.
inline int & Get_K() noexcept
{
    return g_k;
}

回答by Attila

The linker tells you that you have the variable kdefined multiple times. Indeed, you have a definition in A.cpp and another in B.cpp. Both compilation units produce a corresponding object file that the linker uses to create your program. The problem is that in your case the linker does not know whic definition of kto use. In C++ you can have only one defintion of the same construct (variable, type, function).

链接器告诉您该变量k定义了多次。实际上,您在 A.cpp 中有一个定义,在 B.cpp 中有另一个定义。两个编译单元都会生成链接器用来创建程序的相应目标文件。问题是,在您的情况下,链接器不知道k要使用的定义。在 C++ 中,同一构造(变量、类型、函数)只能有一个定义。

To fix it, you will have to decide what your goal is

要解决它,您必须决定您的目标是什么

  • If you want to have two variables, both named k, you can use an anonymous namespace in both .cpp files, then refer to kas you are doing now:
  • 如果你想有两个变量,都命名为k,你可以在两个 .cpp 文件中使用匿名命名空间,然后参考k你现在所做的:

.

.

namespace {
  int k;
}
  • You can rename one of the ks to something else, thus avoiding the duplicate defintion.
  • If you want to have only once definition of kand use that in both .cpp files, you need to declare in one as extern int k;, and leave it as it is in the other. This will tell the linker to use the one definition (the unchanged version) in both cases -- externimplies that the variable is defined in another compilation unit.
  • 您可以将ks之一重命名为其他名称,从而避免重复定义。
  • 如果您只想k在两个 .cpp 文件中定义并使用它,则需要在其中一个声明为extern int k;,而在另一个中保持原样。这将告诉链接器在两种情况下都使用一个定义(未更改的版本)——extern意味着该变量是在另一个编译单元中定义的。