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

Tom*_*ica 27 c++ oop boost include visual-studio-2010

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

main.cpp中

#include "main.h";
Run Code Online (Sandbox Code Playgroud)

main.h

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.cpp"
Run Code Online (Sandbox Code Playgroud)

client.cpp

#ifndef SOCKET_CLIENT_CLASS
#define SOCKET_CLIENT_CLASS
#ifndef BOOST_ASIO_HPP
#include <boost/asio.hpp>
#endif
/*CLASS DEFINITION HERE*/
#endif
Run Code Online (Sandbox Code Playgroud)

这就是编译器抱怨的:

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

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

正如你所看到的,我不是双重定义/包括我的类,它只包含在main.h中一次.那么这里发生了什么? 我已经阅读了这个答案,但没有任何帮助,因为它预计会有双重包含.投票支持复制之前,请将此事实纳入考虑范围,因为这只是意味着无端地斩首我.

And*_*owl 46

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

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

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

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

client.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
Run Code Online (Sandbox Code Playgroud)

client.cpp

#include "Client.h"

// ...

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

// ... (add the definitions for all other member functions)
Run Code Online (Sandbox Code Playgroud)

main.h

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.h"
//              ^^ Notice this!
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include "main.h"
Run Code Online (Sandbox Code Playgroud)

  • @TomášZato有关将代码正确分离为.cpp和.h文件的说明,请参阅[此答案](http://stackoverflow.com/a/333964/1227469). (2认同)

小智 12

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

\n
inline void functionX() \n{ }\n
Run Code Online (Sandbox Code Playgroud)\n

有关内联函数的更多信息:

\n
\n

内联函数是 C++ 的增强功能,用于增加程序的执行时间。可以指示编译器将函数设为内联,以便编译器可以在调用函数时替换这些函数定义。编译器在编译时替换内联函数的定义,而不是在运行时引用函数定义。\n注意-这只是建议编译器使函数内联,如果函数很大(就可执行指令等而言),则编译器可以忽略 \xe2\x80\x9cinline\xe2\x80\x9d 请求并将该函数视为正常函数。

\n
\n

更多信息在这里

\n


wil*_*ick 9

你可能不想这样做:

#include "client.cpp"
Run Code Online (Sandbox Code Playgroud)

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

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

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