wake-up-neo.com

C++ - Redefinitions-Header-Dateien (winsock2.h)

Wie kann ich verhindern, dass Headerdateien zweimal eingefügt werden? Das Problem ist, ich füge diein MyClass.h hinzu und dann füge ich MyClass.h in vielen Dateien ein. Wie man etwas vorbeugt?

Ich verwende #pragma einmal anstelle von Include-Wachen, 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: Ich bekomme nur wenige Fehler

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'
120
akif

Dieses Problem wird verursacht, wenn <windows.h> vor <winsock2.h> eingefügt wird. Ordnen Sie Ihre Include-Liste so an, dass <windows.h> nach <winsock2.h> enthalten ist, oder definieren Sie _WINSOCKAPI_ zuerst

#define _WINSOCKAPI_    // stops windows.h including winsock.h
#include <windows.h>
// ...
#include "MyClass.h"    // Which includes <winsock2.h>

Siehe auch dies .

203
pingw33n

Wie von anderen vorgeschlagen, besteht das Problem, wenn windows.h vor WinSock2.h eingefügt wird. Weil windows.hwinsock.h enthält. Sie können nicht WinSock2.h und winsock.h verwenden.

Lösungen:

  • Fügen Sie WinSock2.h vor windows.h ein. Bei vorkompilierten Headern sollten Sie es dort lösen. Bei einem einfachen Projekt ist es einfach. In großen Projekten (insbesondere beim Schreiben von tragbarem Code ohne vorkompilierte Header) kann dies jedoch sehr schwierig sein, denn wenn Ihr Header mit WinSock2.h enthalten ist, kann windows.h bereits aus einer anderen Header-/Implementierungsdatei enthalten sein.

  • Definieren Sie WIN32_LEAN_AND_MEAN vor windows.h oder projektweit. Aber es schließt viele andere Dinge aus, die Sie benötigen, und Sie sollten es selbst hinzufügen.

  • Definieren Sie _WINSOCKAPI_ vor windows.h oder projektweit. Wenn Sie jedoch WinSock2.h einschließen, erhalten Sie eine Warnung zur Makro-Neudefinition.

  • Verwenden Sie windows.h anstelle von WinSock2.h, wenn winsock.h für Ihr Projekt ausreicht (in den meisten Fällen ist dies der Fall). Dies führt wahrscheinlich zu einer längeren Übersetzungszeit, behebt jedoch alle Fehler/Warnungen.

69
Pavel Machyniak

Mit "Header Guards":

#ifndef MYCLASS_H
#define MYCLASS_H

// This is unnecessary, see comments.
//#pragma once

// MyClass.h

#include <winsock2.h>

class MyClass
{

// methods
public:
    MyClass(unsigned short port);
    virtual ~MyClass(void);
};

#endif
14
DevSolar

Oh - die Hässlichkeit von Windows ... Die Reihenfolge der Include-Einstellungen ist hier wichtig. Sie müssen winsock2.h vor windows.h einschließen. Da windows.h wahrscheinlich aus Ihrem vorkompilierten Header (stdafx.h) enthalten ist, müssen Sie von dort aus die Datei winsock2.h einfügen:

#include <winsock2.h>
#include <windows.h>
13
Daniel Paull

Ich bin auf dieses Problem gestoßen, als ich versuchte, ein Paket eines Drittanbieters zu ziehen, das anscheinend windows.h irgendwo in seinem Durcheinander von Kopfzeilen enthielt. Das Definieren von _WINSOCKAPI_ auf Projektebene war viel einfacher (ganz zu schweigen von mehr zu pflegen), als durch die Suppe zu waten und das problematische Include zu beheben.

6
Yaur

Ich würde nicht nur FILENAME_H Verwenden, sondern

#ifndef FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD
#define FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD

//code stuff
#endif // FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD

Ich habe immer eine Postfix-Guid verwendet. Ich bin vor einigen Jahren auf eine sehr schlechte Codebasis gestoßen, die unterschiedliche Header-Dateien mit demselben Dateinamen und Include-Guard hatte. Die fraglichen Dateien hatten eine Klasse mit demselben Namen definiert. Wenn nur Namespaces verwendet wurden. Einige Projekte haben einige nicht zusammengestellt. Die Verwendung einzigartiger Schutzeinrichtungen war ein Teil der Lösung bei der Unterscheidung von Kopfzeilen und deren Inhalten.

Verwenden Sie unter Windows mit Visual Studio die Datei guidgen.exe, unter Linux uuidgen -t.

4
Sam

Ich habe diesen Link windows.h und winsock2.h gefunden, der eine Alternative hat, die für mich gut funktioniert hat:

#define _WINSOCKAPI_    // stops windows.h including winsock.h
#include <windows.h>
#include <winsock2.h>

Ich hatte Probleme, den Ort zu finden, an dem das Problem auftrat, aber durch Hinzufügen dieses # Defines konnte ich bauen, ohne es herauszufinden. 

4

Ich habe die rekursiven Include-Dateien überprüft. Ich habe die Header-Dateien entdeckt, die (rekursiv) #include "windows.h" und "#include" Winsock.h "and write a # Include" Winsock2.h ". in this files, i added # Include" Winsock2.h "` als erstes Include enthalten.

Nur eine Frage der Geduld, schauen Sie sich die Includes einzeln an und legen Sie diese Reihenfolge fest, zuerst #include "Winsock2.h", dann #include "windows.h"

3
octoback

In VS 2015 wird Folgendes funktionieren:

#define _WINSOCKAPI_

Während das Folgende nicht gilt:

#define WIN32_LEAN_AND_MEAN
3
MariuszW

Ich bin auf dieselbe Ausgabe gestoßen und hier ist das, was ich bisher entdeckt habe:

Aus diesem Ausgabefragment - 

 c:\Programme\Microsoft sdks\windows\v6.0a\include\ws2def.h (91): Warnung C4005: 'AF_IPX': Makro-Neudefinition 
 c:\Programme\Microsoft sdks\windows\v6.0a\include\winsock.h (460): Siehe vorherige Definition von 'AF_IPX' 

-Es scheint, dass sowohl ws2def.h als auch winsock.h in Ihre Lösung aufgenommen wurden.

Wenn Sie sich die Datei ws2def.h ansehen, beginnt sie mit dem folgenden Kommentar -

/*++

Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:

    ws2def.h

Abstract:

    This file contains the core definitions for the Winsock2
    specification that can be used by both user-mode and 
    kernel mode modules.

    This file is included in WINSOCK2.H. User mode applications
    should include WINSOCK2.H rather than including this file
    directly. This file can not be included by a module that also
    includes WINSOCK.H.

Environment:

    user mode or kernel mode

--*/

Beachten Sie die letzte Zeile - "Diese Datei kann nicht von einem Modul eingeschlossen werden, das auch WINSOCK.H enthält."

Versuchen Sie weiterhin, das Problem zu beheben, ohne Änderungen am Code vorzunehmen.

Lassen Sie mich wissen, ob dies sinnvoll ist.

3

#pragma once basiert auf dem vollständigen Pfad des Dateinamens. Wahrscheinlich haben Sie also zwei identische Kopien von MyClass.h oder Winsock2.h in verschiedenen Verzeichnissen.

2
soru

Sie sollten Header Guard verwenden.

setzen Sie diese Zeile am Anfang der Headerdatei

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

und am Boden

#endif
2
ntcong

#include Guards sind die Standardmethoden dafür. #pragma once ist nicht, bedeutet, dass nicht alle Compiler dies unterstützen.

1
Dima

In meinem Projekt (ich verwende VS 2008 SP1) funktioniert die nächste Lösung:

Header-Datei:

//myclass.h
#pragma once
#define _WINSOCKAPI_
#include <windows.h>

Cpp-Klasse:

//myclass.cpp
#include "Util.h"
#include "winsock2class.h"
#pragma comment(lib, "Ws2_32.lib")

dabei bedeutet #include "winsock2class.h" die Klasse, die winsock2.h implementiert hat:

//winsock2class.h
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
1
Yahor M

#pragma once ist selbst für MS-Compiler Flakey und wird von vielen anderen Compilern nicht unterstützt. Wie viele andere Leute erwähnt haben, ist die Verwendung von Include-Guards der richtige Weg. Verwenden Sie #pragma once nicht - es wird Ihnen das Leben erleichtern.

1
Thomi

Ich bin eigentlich auf ein Problem gestoßen, bei dem ich winsock2.h als erstes include definieren musste. Ich hoffe, das ist hilfreich für jemanden, der dasselbe Problem hat, nicht nur windows.h, sondern alle.

0
Jeff