40

我碰巧得到了 .obj 错误中已经定义的那个。这是我的项目的结构:

主文件

#include "main.h";

主文件

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

客户端.cpp

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

这就是编译器所抱怨的:

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

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

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

4

3 回答 3

62

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

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

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

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

客户端.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

客户端.cpp

#include "Client.h"

// ...

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

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

主文件

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

主文件

#include "main.h"
于 2013-03-14T22:24:30.120 回答
13

你可能不想这样做:

#include "client.cpp"

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

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

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

于 2013-03-14T22:26:07.160 回答
5

我确实建议在 2 个填充(.h .cpp)中执行它但是如果你懒惰只是inline在函数之前添加所以它看起来像这样

inline void functionX() 
{ }

更多关于内联函数:

内联函数是 C++ 增强功能,用于增加程序的执行时间。函数可以被指示编译器使它们内联,以便编译器可以在任何被调用的地方替换那些函数定义。编译器在编译时替换内联函数的定义,而不是在运行时引用函数定义。注意 - 这只是对编译器的建议,使函数内联,如果函数很大(就可执行指令等而言),编译器可以忽略“内联”请求并将函数视为普通函数。

更多信息在这里

于 2020-06-26T19:38:38.460 回答