Wie verhindere ich, dass Header-Dateien zweimal eingefügt werden? Das Problem ist, ich schließe diein MyClass.h und dann füge ich MyClass.h in viele Dateien ein, so dass es mehrmals enthält und ein Neudefinitionsfehler auftritt. Wie man etwas vorbeugt?
Ich benutze #pragma einmal, anstatt Wachen einzuschließen, und ich denke, das ist in Ordnung.
MyClass.h:
// MyClass.h
#pragma once
#include <winsock2.h>
class MyClass
{
// methods
public:
MyClass(unsigned short port);
virtual ~MyClass(void);
};
EDIT: Einige der Fehler, die ich bekomme
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(91) : warning C4005: 'AF_IPX' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(460) : see previous definition of 'AF_IPX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(124) : warning C4005: 'AF_MAX' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(479) : see previous definition of 'AF_MAX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(163) : warning C4005: 'SO_DONTLINGER' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(402) : see previous definition of 'SO_DONTLINGER'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(206) : error C2011: 'sockaddr' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(485) : see declaration of 'sockaddr'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing '}' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing ';' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2059: syntax error : 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C2143: syntax error : missing ';' before '}'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(518) : warning C4005: 'IN_CLASSA' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(287) : see previous definition of 'IN_CLASSA'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(524) : warning C4005: 'IN_CLASSB' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(293) : see previous definition of 'IN_CLASSB'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(530) : warning C4005: 'IN_CLASSC' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(299) : see previous definition of 'IN_CLASSC'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(541) : warning C4005: 'INADDR_ANY' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(304) : see previous definition of 'INADDR_ANY'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(543) : warning C4005: 'INADDR_BROADCAST' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(306) : see previous definition of 'INADDR_BROADCAST'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(577) : error C2011: 'sockaddr_in' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(312) : see declaration of 'sockaddr_in'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(132) : error C2011: 'fd_set' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(68) : see declaration of 'fd_set'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(167) : warning C4005: 'FD_SET' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(102) : see previous definition of 'FD_SET'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(176) : error C2011: 'timeval' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(111) : see declaration of 'timeval'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(232) : error C2011: 'hostent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(167) : see declaration of 'hostent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(245) : error C2011: 'netent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(180) : see declaration of 'netent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(252) : error C2011: 'servent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(187) : see declaration of 'servent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(264) : error C2011: 'protoent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(199) : see declaration of 'protoent'
c++
header
redefinition
akif
quelle
quelle
Antworten:
Dieses Problem wird beim vorherigen
<windows.h>
Einfügen verursacht<winsock2.h>
. Versuchen Sie, Ihre Include-Liste zu ordnen,<windows.h>
die nach<winsock2.h>
oder_WINSOCKAPI_
zuerst definiert wird :Siehe auch dies .
quelle
<winsock2.h>
in MSVC2008 in Ordnung.<windows.h>
Durch die Aufnahme werden identische Kompilierungsfehler generiert, die Sie angegeben haben.#include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>
in Ordnung und bekam Winsock2, h Datei nicht gefunden. Inbegriffen#define _WINSOCKAPI_
vor allem 3 enthält noch den gleichen FehlerWie andere vorgeschlagen haben, liegt das Problem darin, wann
windows.h
es zuvor enthalten istWinSock2.h
. Weilwindows.h
beinhaltetwinsock.h
. Sie können nicht beideWinSock2.h
und verwendenwinsock.h
.Lösungen:
WinSock2.h
Vorher einschließenwindows.h
. Bei vorkompilierten Headern sollten Sie diese dort lösen. Bei einem einfachen Projekt ist es einfach. In großen Projekten (insbesondere beim Schreiben von portablem Code ohne vorkompilierte Header) kann dies jedoch sehr schwierig sein, da der Header mit bereits in einer anderen Header- / ImplementierungsdateiWinSock2.h
enthalten seinwindows.h
kann, wenn er enthalten ist.WIN32_LEAN_AND_MEAN
Vorher definierenwindows.h
oder projektweit. Aber es schließt viele andere Dinge aus, die Sie möglicherweise benötigen, und Sie sollten es selbst einschließen._WINSOCKAPI_
Vorher definierenwindows.h
oder projektweit. Wenn Sie jedoch einschließen, erhaltenWinSock2.h
Sie eine Warnung zur Neudefinition von Makros.Verwenden Sie
windows.h
anstelle von "WinSock2.h
Wann"winsock.h
für Ihr Projekt ausreicht (in den meisten Fällen). Dies führt wahrscheinlich zu einer längeren Kompilierungszeit, behebt jedoch alle Fehler / Warnungen.quelle
WIN32_LEAN_AND_MEAN
war die Lösung für mich Panzer viel_WINSOCK_
Lösung: Sie sollten keine Warnung zur Neudefinition von Makros erstellen, wenn beide Definitionen identisch sind. Der häufigste Fehler ist, dass Benutzer dem Projekt eine Definition hinzufügen, ohne einen Wert festzulegen, und eine leere Definition erwarten. Wenn Sie jedoch-D_WINSOCK_
zur cmd-Zeile hinzufügen , wird diese_WINSOCK_
auf 1 gesetzt. Um eine leere Definition zu erstellen,-D_WINSOCK_=
muss diese übergeben werden.#define _WINSOCKAPI_
, benötigen Sie möglicherweise auch#define _WINSOCK_DEPRECATED_NO_WARNINGS
, abhängig von Ihren Umständen.Oh - die Hässlichkeit von Windows ... Die Reihenfolge der Einschlüsse ist hier wichtig. Sie müssen winsock2.h vor windows.h einfügen. Da windows.h wahrscheinlich in Ihrem vorkompilierten Header (stdafx.h) enthalten ist, müssen Sie von dort aus wonock2.h einschließen:
quelle
Mit "Header Guards":
quelle
Ich bin auf dieses Problem gestoßen, als ich versucht habe, ein Paket eines Drittanbieters abzurufen, das anscheinend windows.h irgendwo in der Menge der Header enthielt. Das Definieren
_WINSOCKAPI_
auf Projektebene war viel einfacher (ganz zu schweigen von der Wartbarkeit), als durch die Suppe zu waten und das problematische Include zu beheben.quelle
DEFINES += _WINSOCKAPI_
In VS 2015 funktioniert Folgendes:
Während die folgenden nicht:
quelle
Ich überprüfte die rekursive enthält, habe ich die Header - Dateien entdeckt , die umfassen (rekursiv) einige
#include "windows.h"
und#include "Winsock.h"
und schreiben#include "Winsock2.h"
. In diesen Dateien habe ich#include "Winsock2.h"
als erstes Include hinzugefügt .Nur eine Frage der Geduld, Blick auf beinhaltet eine nach der anderen und dieser Ordnung zu schaffen, zuerst
#include "Winsock2.h"
dann#include "windows.h"
quelle
Ich habe diesen Link windows.h und winsock2.h gefunden, der eine Alternative hat, die für mich großartig funktioniert hat:
Ich hatte Probleme zu finden, wo das Problem aufgetreten ist, aber durch Hinzufügen von #define konnte ich erstellen, ohne es herauszufinden.
quelle
Ich würde aber nicht nur FILENAME_H verwenden
Ich habe immer einen Postfix Guid verwendet. Ich bin vor einigen Jahren auf eine sehr schlechte Codebasis gestoßen, die verschiedene Header-Dateien mit demselben Dateinamen und Guard enthielt. Die fraglichen Dateien hatten eine gleichnamige Klasse definiert. Wenn nur Namespaces verwendet würden. Einige Projekte wurden kompiliert, andere nicht. Die Verwendung eindeutiger Schutzvorrichtungen war ein Teil der Lösung bei der Unterscheidung von Headern und deren Inhalten.
Verwenden Sie unter Windows mit Visual Studio guidgen.exe, unter Linux uuidgen -t.
quelle
Ich bin auf dasselbe Problem gestoßen und habe Folgendes bisher entdeckt:
Aus diesem Ausgabefragment -
-Es scheint, dass sowohl ws2def.h als auch winsock.h in Ihrer Lösung enthalten sind.
Wenn Sie sich die Datei ws2def.h ansehen, beginnt sie mit dem folgenden Kommentar:
Beachten Sie die letzte Zeile - "Diese Datei kann nicht von einem Modul aufgenommen werden, das auch WINSOCK.H enthält."
Ich versuche immer noch, das Problem zu beheben, ohne Änderungen am Code vorzunehmen.
Lassen Sie mich wissen, ob dies sinnvoll ist.
quelle
Sie sollten Header Guard verwenden.
Setzen Sie diese Zeile oben in die Header-Datei
und unten
quelle
#pragma once
basiert auf dem vollständigen Pfad des Dateinamens. Sie haben also wahrscheinlich zwei identische Kopien von MyClass.h oder Winsock2.h in verschiedenen Verzeichnissen.quelle
#pragma once
ist selbst auf MS-Compilern ein Flakey und wird von vielen anderen Compilern nicht unterstützt. Wie viele andere bereits erwähnt haben, ist die Verwendung von Include-Wachen der richtige Weg. Verwenden Sie es#pragma once
überhaupt nicht - es wird Ihr Leben viel einfacher machen.quelle
#pragma once
der Compiler den Knotennamen der Header-Datei als eindeutige ID. Dies kann fehlschlagen, wenn Sie symbolische Links oder NTFS-Junctions in Ihrem Quellbaum haben (häufiger als Sie vielleicht denken) oder wenn Sie eine gleichnamige Datei in einem anderen System-Include-Verzeichnis haben (dies ist mir schon einmal passiert, als ich es getan habe Version 1 und Version 2 derselben Bibliothek, die auf zwei verschiedenen Systemen installiert sind, enthalten Pfade. Fazit: Für mich ist es mir lieber, mehr Kontrolle zu haben und mit gelegentlichen Wetware-Fehlern zu leben, als einem Compiler zu vertrauen, der dies für mich erledigt.# Include Guards sind die Standardmethode. #pragma ist einmal nicht, was bedeutet, dass nicht alle Compiler es unterstützen.
quelle
In meinem Projekt (ich verwende VS 2008 SP1) funktioniert nächste Lösung:
Header-Datei:
Cpp-Klasse:
Dabei bedeutet #include "winsock2class.h" die Klasse, die winockock2.h implementiert hat:
quelle
Ich bin tatsächlich auf ein Problem gestoßen, bei dem ich winsock2.h als erstes Include definieren musste. Es scheint, dass es andere Probleme mit Includes aus anderen Paketen gibt. Ich hoffe, dies ist hilfreich für jemanden, der auf dasselbe Problem stößt, nicht nur auf windows.h, sondern auf alles.
quelle