Il m'est arrivé d'obtenir ce déjà défini dans l'erreur .obj. C'est la structure de mon projet:
#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
C'est ce que le compilateur se plaint:
main.obj: erreur LNK2005: "public: bool __thiscall SocketClient :: read (int, char *)" (? read @ SocketClient @@ QAE_NHPAD @ Z) déjà défini dans client.obj
Notez qu'il se plaint de ma classe, pas de boost. Une chose intéressante est que lorsque je supprime #include <boost/asio.hpp>
de client.cpp , je reçois des erreurs thouhg il est aussi inclus dans main.h .
Comme vous pouvez le voir, je ne définis pas/y compris ma classe, elle est incluse exactement une fois dans main.h =. Alors qu'est-ce qui se passe ici?
J'ai lu cette réponse , mais cela ne m'a pas aidé, car il attend des doubles inclusions. Prenez ce fait en considération avant de voter pour un double, car cela signifie simplement me décapiter sans pitié.
Ce n'est pas une erreur du compilateur : l'erreur provient de l'éditeur de liens . Après la compilation, l'éditeur de liens fusionnera les fichiers objets résultant de la compilation de chacune de vos unités de traduction (.cpp
des dossiers).
L'éditeur de liens découvre que le même symbole est défini plusieurs fois dans différentes unités de traduction et s'en plaint (il s'agit d'une violation de la règle de définition unique).
La raison en est certainement que main.cpp
comprend client.cpp
, et ces deux fichiers sont traités individuellement par le compilateur pour produire deux fichiers objets séparés. Par conséquent, tous les symboles définis dans le client.cpp
l'unité de traduction sera également définie dans le main.cpp
unité de traduction. C'est l'une des raisons pour lesquelles vous n'avez généralement pas #include
.cpp
des dossiers.
Mettez la définition de votre classe dans un client.hpp
fichier qui ne pas contient également les définitions des fonctions membres de cette classe; puis laissez client.cpp
et main.cpp
inclure ce fichier (je veux dire #include
). Enfin, laissez dans client.cpp
les définitions des fonctions membres de votre classe.
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"
Vous ne voulez probablement pas faire ceci:
#include "client.cpp"
Un fichier * .cpp aura été compilé par le compilateur dans le cadre de votre build. En l'incluant dans d'autres fichiers, il sera compilé à nouveau (et encore!) Dans chaque fichier dans lequel vous l'incluez.
Maintenant, voici la chose: Vous le gardez avec #ifndef SOCKET_CLIENT_CLASS
, cependant, chaque fichier contenant #include "client.cpp"
est construit indépendamment et comme tel trouvera SOCKET_CLIENT_CLASS
pas encore défini. Par conséquent, son contenu sera inclus, et non # ifdef'd out.
S'il contient des définitions (plutôt que de simples déclarations), ces définitions seront répétées dans chaque fichier où il est inclus.