私はたまたま.objエラーで既に定義されているものを取得しました。これは私のプロジェクトの構造です:
#include "main.h";
#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.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)already defined client.obj内
ブーストではなく、クラスについて不平を言っていることに注意してください。興味深いことに、#include <boost/asio.hpp>
をclient.cppから削除すると、エラーが発生しますmain.hにも含まれています。
ご覧のように、クラスを二重に定義/インクルードしているわけではありません。インクルードexactly once inmain.h。ここで何が起こっているのでしょうか?
私は この回答 を読みましたが、二重の包含を期待するため、助けにはなりませんでした。これは単に容赦なく私を斬首することを意味するので、この事実を複製に投票する前に監視してください。
これはcompilerエラーではありません:エラーはlinkerから発生しています。コンパイル後、リンカは各翻訳単位のコンパイルの結果のオブジェクトファイル(.cpp
ファイル)をマージします。
リンカは、異なる翻訳単位で同じシンボルが複数回定義されていることを知り、それについて文句を言います(1つの定義ルールに違反しています)。
main.cpp
にはclient.cpp
が含まれており、これらのファイルは両方ともコンパイラーによって個別に処理され、twoが生成されるためです。オブジェクトファイル。したがって、client.cpp
翻訳単位で定義されているすべてのシンボルは、main.cpp
翻訳単位でも定義されます。これは、通常#include
.cpp
ファイルを使用しない理由の1つです。
クラスの定義を、そのクラスのメンバー関数の定義も含むnotを含む別のclient.hpp
ファイルに入れます。次に、client.cpp
とmain.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
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"
あなたはおそらくこれをしたくないでしょう:
#include "client.cpp"
* .cppファイルは、ビルドの一部としてコンパイラーによってコンパイルされます。他のファイルに含めることで、それを含むすべてのファイルで再度コンパイルされます(そして再び!)。
今ここにあります:#ifndef SOCKET_CLIENT_CLASS
で保護していますが、#include "client.cpp"
を持つ各ファイル独立してビルドされますなので、SOCKET_CLIENT_CLASS
はまだ定義されていません。したがって、#ifdefで除外されたものではなく、その内容が含まれます。
(宣言ではなく)定義がまったく含まれている場合、これらの定義は含まれるすべてのファイルで繰り返されます。