C++ 已在 .obj 中定义 - 没有双重包含

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15421254/
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 19:21:02  来源:igfitidea点击:

Already defined in .obj - no double inclusions

c++visual-studio-2010oopboostinclude

提问by Tomá? Zato - Reinstate Monica

I happened to get that already defined in .obj error. This is structure of my project:

我碰巧在 .obj 错误中已经定义了它。这是我的项目的结构:

main.cpp

主程序

#include "main.h";

main.h

主文件

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.cpp"

client.cpp

客户端

#ifndef SOCKET_CLIENT_CLASS
#define SOCKET_CLIENT_CLASS
#ifndef BOOST_ASIO_HPP
#include <boost/asio.hpp>
#endif
/*CLASS DEFINITION HERE*/
#endif

This is what compiler is complaining about:

这就是编译器抱怨的:

main.obj : error LNK2005: "public: bool __thiscall SocketClient::read(int,char *)" (?read@SocketClient@@QAE_NHPAD@Z) already definedin client.obj

main.obj : error LNK2005: "public: bool __thiscall SocketClient::read(int,char *)" (?read@SocketClient@@QAE_NHPAD@Z)在 client.obj 中定义

Note it is complaining about my class, not boost. One interesting thing is, that when I remove #include <boost/asio.hpp>from client.cpp, I get errors thouhg it is included in main.h too.

请注意,它是在抱怨我的课程,而不是提升。一件有趣的事情是,当我#include <boost/asio.hpp>client.cpp 中删除时,我收到错误消息,它也包含在 main.h 中

As you can see, I'm not double defining/including my class, its included exactly oncein main.h. So what's going on here?
I have read this answer, but it was no help, since it expects double inclusions. Take this fact into osideration before voting for duplicate, because this simply means beheading me without mercy.

正如你所看到的,我没有双重定义/包括我的类,它在main.h包含一次。那么这里发生了什么? 我已经阅读了这个答案,但它没有帮助,因为它需要双重包含。在投票给重复之前考虑这个事实,因为这只是意味着毫不留情地斩首我。

回答by Andy Prowl

This is not a compilererror: the error is coming from the linker. After compilation, the linker will merge the object files resulting from the compilation of each of your translation units (.cppfiles).

这不是编译器错误:错误来自链接器。编译后,链接器将合并由每个翻译单元(.cpp文件)编译产生的目标文件。

The linker finds out that you have the same symbol defined multiple times in different translation units, and complains about it (it is a violation of the One Definition Rule).

链接器发现你在不同的翻译单元中多次定义了相同的符号,并抱怨它(这违反了一个定义规则)。

The reason is most certainly that main.cppincludes client.cpp, and both these files are individually processed by the compiler to produce twoseparate object files. Therefore, all the symbols defined in the client.cpptranslation unit will be defined also in the main.cpptranslation unit. This is one of the reasons why you do not usually #include.cppfiles.

原因肯定是main.cpp包含client.cpp,并且这两个文件都由编译器单独处理以生成两个单独的目标文件。因此,client.cpp翻译单元中定义的所有符号也将在翻译单元中定义main.cpp。这是您通常不归档的原因之一#include.cpp

Put the definition of your class in a separate client.hppfile which does notcontain also the definitions of the member functions of that class; then, let client.cppand main.cppinclude that file (I mean #include). Finally, leave in client.cppthe definitions of your class's member functions.

将类的定义放在一个单独的client.hpp文件中,该文件包含该类的成员函数的定义;然后,让client.cppmain.cpp包含该文件(我的意思是#include)。最后,保留client.cpp类成员函数的定义。

client.h

客户端.h

#ifndef SOCKET_CLIENT_CLASS
#define SOCKET_CLIENT_CLASS
#ifndef BOOST_ASIO_HPP
#include <boost/asio.hpp>
#endif

class SocketClient // Or whatever the name is...
{

// ...

    bool read(int, char*); // Or whatever the name is...

//  ...
};

#endif

client.cpp

客户端

#include "Client.h"

// ...

bool SocketClient::read(int, char*)
{
    // Implementation  goes here...
}

// ... (add the definitions for all other member functions)

main.h

主文件

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.h"
//              ^^ Notice this!

main.cpp

主程序

#include "main.h"

回答by wilsonmichaelpatrick

You probably don't want to do this:

你可能不想这样做:

#include "client.cpp"

A *.cpp file will have been compiled by the compiler as part of your build. By including it in other files, it will be compiled again (and again!) in every file in which you include it.

*.cpp 文件将作为构建的一部分由编译器编译。通过将它包含在其他文件中,它将在包含它的每个文件中再次编译(并且再次!)。

Now here's the thing:You are guarding it with #ifndef SOCKET_CLIENT_CLASS, however, each file that has #include "client.cpp"is built independentlyand as such will find SOCKET_CLIENT_CLASSnot yet defined. Therefore it's contents will be included, not #ifdef'd out.

现在事情是这样的:你用 来保护它#ifndef SOCKET_CLIENT_CLASS,但是,每个拥有的文件#include "client.cpp"都是独立构建的,因此会发现SOCKET_CLIENT_CLASS尚未定义。因此它的内容将被包括在内,而不是#ifdef'd。

If it contains any definitions at all (rather than just declarations) then these definitions will be repeated in every file where it's included.

如果它包含任何定义(而不仅仅是声明),那么这些定义将在包含它的每个文件中重复。

回答by MOHAMMAD WASEEM

This is one of the method to overcome this issue.

这是克服这个问题的方法之一。

  • Just put the prototype in the header files and include the header files in the .cpp files as shown below.
  • 只需将原型放在头文件中,并将头文件包含在 .cpp 文件中,如下所示。

client.cpp

客户端

#ifndef SOCKET_CLIENT_CLASS
#define SOCKET_CLIENT_CLASS
#ifndef BOOST_ASIO_HPP
#include <boost/asio.hpp>
#endif

class SocketClient // Or whatever the name is... {

// ...

    bool read(int, char*); // Or whatever the name is...

//  ... };

#endif

client.h

客户端.h

bool SocketClient::read(int, char*)
{
    // Implementation  goes here...
}

main.cpp

主程序

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.h"
//              ^^ Notice this!

main.h

主文件

int main()