Al gedefinieerd in .obj – geen dubbele insluitsels

Ik kreeg dat toevallig al gedefinieerd in de .obj-fout. Dit is de structuur van mijn project:

main.cpp

#include "main.h";

hoofd.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

Dit is waar de compiler over klaagt:

main.obj : error LNK2005: “public: bool __thiscall SocketClient::read(int,char *)” (?read@SocketClient@@QAE_NHPAD@Z) al gedefinieerd in client.obj

Let op: het is klagen over mijn klas, niet over boost. Een interessant ding is dat wanneer ik #include <boost/asio.hpp> verwijder van client.cpp, ik fouten krijg, hoewel het is opgenomen in .h ook.

Zoals je kunt zien, definieer/bevat ik mijn klas niet dubbel, het is exact één keer opgenomen in main.h. Dus wat is hier aan de hand?
Ik heb dit antwoord gelezen, maar het hielp niet, omdat het dubbele insluitsels verwacht. Neem dit feit in overweging voordat u op duplicaat stemt, want dit betekent gewoon dat u me zonder pardon onthoofdt.


Antwoord 1, autoriteit 100%

Dit is geen compiler-fout: de fout komt van de linker. Na compilatie zal de linker de objectbestanden samenvoegen die het resultaat zijn van de compilatie van elk van uw vertaaleenheden (.cpp-bestanden).

De linker ontdekt dat je hetzelfde symbool meerdere keren hebt gedefinieerd in verschillende vertaaleenheden, en klaagt erover (het is een overtreding van de One Definition Rule).

De reden is zeer zeker dat main.cpp client.cpp bevat, en beide bestanden worden afzonderlijk door de compiler verwerkt om twee aparte objectbestanden. Daarom worden alle symbolen die zijn gedefinieerd in de vertaaleenheid client.cpp ook gedefinieerd in de vertaaleenheid main.cpp. Dit is een van de redenen waarom u gewoonlijk geen #include .cpp-bestanden gebruikt.

Zet de definitie van je klasse in een apart client.hpp-bestand dat niet ook de definities van de lidfuncties van die klasse bevat; laat dan client.cpp en main.cpp dat bestand opnemen (ik bedoel #include). Laat ten slotte in client.cpp de definities van de lidfuncties van uw klas achter.

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"

Antwoord 2, autoriteit 20%

U wilt dit waarschijnlijk niet doen:

#include "client.cpp"

Een *.cpp-bestand zal door de compiler zijn gecompileerd als onderdeel van uw build. Door het in andere bestanden op te nemen, wordt het opnieuw (en opnieuw!) gecompileerd in elk bestand waarin u het opneemt.

Dit is het punt: je bewaakt het met #ifndef SOCKET_CLIENT_CLASS, maar elk bestand met #include "client.cpp" is onafhankelijk gebouwd en zal als zodanig SOCKET_CLIENT_CLASS nog niet gedefinieerd vinden. Daarom wordt de inhoud opgenomen, niet #ifdef’d.

Als het enige definities bevat (in plaats van alleen declaraties), dan worden deze definities herhaald in elk bestand waarin het is opgenomen.


Antwoord 3, autoriteit 5%

Ik raad aan om het in 2 filles te doen (.h .cpp)
Maar als je lui bent, voeg dan gewoon inline toe voor de functie
Dus het ziet er ongeveer zo uit

inline void functionX() 
{ }

meer over inline-functies:

De inline-functies zijn een C++-verbeteringsfunctie om de uitvoeringstijd van een programma te verlengen. Functies kunnen aan de compiler worden opgedragen om ze inline te maken, zodat de compiler die functiedefinities kan vervangen, waar ze ook worden aangeroepen. Compiler vervangt de definitie van inline-functies tijdens het compileren in plaats van verwijzen naar functiedefinities tijdens runtime.
OPMERKING- Dit is slechts een suggestie voor de compiler om de functie inline te maken, als de functie groot is (in termen van uitvoerbare instructies, enz.), dan kan de compiler het ‘inline’-verzoek negeren en de functie als een normale functie behandelen.

meer info hier


Antwoord 4

Dit is een van de manieren om dit probleem op te lossen.

  • Plaats het prototype in de header-bestanden en voeg de header-bestanden toe aan de .cpp-bestanden, zoals hieronder wordt weergegeven.

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

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()

LEAVE A REPLY

Please enter your comment!
Please enter your name here

one + 19 =

Other episodes