Fichiers D'en-tête de redéfinition C++ (winsock2.h)

Comment puis-je empêcher d'inclure des fichiers d'en-tête deux fois? Le problème est que j'inclus le dans MyClass.h et puis j'inclus MyClass.h dans de nombreux fichiers, donc il inclut plusieurs fois et une erreur de redéfinition se produit. Comment prévenir?

j'utilise # pragma une fois au lieu de include guards, et je suppose que c'est très bien.

MyClass.h:

// MyClass.h
#pragma once

#include <winsock2.h>

class MyClass
{

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

EDIT: Quelques erreurs que je suis

c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(91) : warning C4005: 'AF_IPX' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(460) : see previous definition of 'AF_IPX'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(124) : warning C4005: 'AF_MAX' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(479) : see previous definition of 'AF_MAX'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(163) : warning C4005: 'SO_DONTLINGER' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(402) : see previous definition of 'SO_DONTLINGER'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(206) : error C2011: 'sockaddr' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(485) : see declaration of 'sockaddr'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(384) : error C2143: syntax error : missing '}' before 'constant'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(384) : error C2143: syntax error : missing ';' before 'constant'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(384) : error C2059: syntax error : 'constant'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(437) : error C2143: syntax error : missing ';' before '}'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(518) : warning C4005: 'IN_CLASSA' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(287) : see previous definition of 'IN_CLASSA'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(524) : warning C4005: 'IN_CLASSB' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(293) : see previous definition of 'IN_CLASSB'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(530) : warning C4005: 'IN_CLASSC' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(299) : see previous definition of 'IN_CLASSC'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(541) : warning C4005: 'INADDR_ANY' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(304) : see previous definition of 'INADDR_ANY'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(543) : warning C4005: 'INADDR_BROADCAST' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(306) : see previous definition of 'INADDR_BROADCAST'
c:program filesmicrosoft sdkswindowsv6.0aincludews2def.h(577) : error C2011: 'sockaddr_in' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(312) : see declaration of 'sockaddr_in'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(132) : error C2011: 'fd_set' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(68) : see declaration of 'fd_set'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(167) : warning C4005: 'FD_SET' : macro redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(102) : see previous definition of 'FD_SET'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(176) : error C2011: 'timeval' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(111) : see declaration of 'timeval'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(232) : error C2011: 'hostent' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(167) : see declaration of 'hostent'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(245) : error C2011: 'netent' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(180) : see declaration of 'netent'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(252) : error C2011: 'servent' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(187) : see declaration of 'servent'
c:program filesmicrosoft sdkswindowsv6.0aincludewinsock2.h(264) : error C2011: 'protoent' : 'struct' type redefinition
        c:program filesmicrosoft sdkswindowsv6.0aincludewinsock.h(199) : see declaration of 'protoent'
118
demandé sur Leif Gruenwoldt 2009-09-03 13:53:27

15 réponses

ce problème est causé lorsque l'on inclut <windows.h> avant <winsock2.h> . Essayez d'organiser votre liste d'inclusion que <windows.h> est inclus APRÈS <winsock2.h> ou Définir _WINSOCKAPI_ d'abord:

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

Voir aussi this .

196
répondu pingw33n 2009-09-03 11:23:11

comme d'autres l'ont suggéré, le problème est lorsque windows.h est inclus avant WinSock2.h . Parce que windows.h inclut winsock.h . Vous ne pouvez pas utiliser à la fois WinSock2.h et winsock.h .

Solutions:

  • Inclure WinSock2.h avant windows.h . Dans le cas des en-têtes précompilés, vous devez le résoudre. Dans le cas d'un simple projet, c'est facile. Toutefois, dans les grands projets (en particulier lorsque écrire du code portable, sans en-tête précompilé) cela peut être très difficile, car lorsque votre en-tête avec WinSock2.h est inclus, windows.h peut déjà être inclus à partir d'un autre fichier d'en-tête/implémentation.

  • définir WIN32_LEAN_AND_MEAN avant windows.h ou projet à l'échelle. Mais il exclura beaucoup d'autres choses que vous pourriez avoir besoin et vous devriez l'inclure par vos propres.

  • Définir _WINSOCKAPI_ avant windows.h ou projet large. Mais quand vous incluez WinSock2.h vous obtenez avertissement de redéfinition macro.

  • utilisez windows.h au lieu de WinSock2.h quand winsock.h est suffisant pour votre projet (dans la plupart des cas, il est). Il en résultera probablement un temps de compilation plus long mais résoudra les erreurs/avertissements.

67
répondu Pavel Machyniak 2011-11-28 10:47:14

en utilisant "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
répondu DevSolar 2015-02-04 05:20:37

Oh - la laideur des fenêtres... L'ordre des inclusions est important ici. Vous devez inclure winsock2.h avant les fenêtres.h. Depuis windows.h est probablement inclus dans votre en-tête précompilé (stdafx.h), vous aurez besoin d'inclure winsock2.h de là:

#include <winsock2.h>
#include <windows.h>
12
répondu Daniel Paull 2010-07-15 07:24:29

j'ai rencontré ce problème en essayant de tirer un paquet d'une tierce partie qui incluait apparemment windows.h quelque part dans ce fouillis d'entêtes. Définir _WINSOCKAPI_ au niveau du projet a été beaucoup plus facile (pour ne pas mentionner plus maintenable) que patauger dans leur soupe et la réparation de la problématique inclure.

6
répondu Yaur 2009-10-04 19:36:19

Je n'utiliserais pas juste FILENAME_H mais

#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

j'ai toujours utilisé une interface postfix. Je suis tombé sur une base de code très pauvre il y a quelques années qui avait des fichiers d'en-tête différents avec le même nom de fichier et include guard. Les fichiers en question avaient défini une classe avec le même nom. Si seulement des espaces de noms étaient utilisés. Certains projets compilés, d'autres pas. L'utilisation de protecteurs uniques faisait partie de la solution pour différencier les en-têtes et leur contenu.

Sur Windows avec Visual Studio guidgen.exe, sur Linux uuidgen - T.

4
répondu Sam 2009-09-03 11:45:21

j'ai trouvé ce lien windows.h et winsock2.h qui a une alternative qui a bien fonctionné pour moi:

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

j'avais de la difficulté à trouver où le problème s'est produit, mais en ajoutant que #define j'ai pu construire sans le comprendre.

4
répondu Benjamin Herreid 2011-04-01 04:02:20

j'ai rencontré le même problème et voici ce que j'ai découvert jusqu'à présent:

de ce fragment de sortie -

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'

- il semble que les deux ws2def.h et winsock.h ont été inclus dans votre solution.

si vous regardez le fichier ws2def.h il commence par le commentaire suivant:

/*++

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

--*/

attention à la dernière ligne ("Ce fichier ne peut pas être compris par un module qui aussi comprend WINSOCK.H"

essaie toujours de corriger le problème sans apporter de modifications au code.

dites-moi si cela a un sens.

3
répondu Shailesh Tainwala 2012-01-09 08:37:46

j'ai vérifié les inclusions récursives, j'ai repéré les fichiers d'en-tête qui incluent (récursivement) quelques #include "windows.h" et "#include " Winsock.h" and write a #include " Winsock2.h" . in this files, i added #include " Winsock2.h"` la première inclure.

juste une question de patience, regarder inclut un par un et établir cet ordre, d'abord #include "Winsock2.h" puis #include "windows.h"

3
répondu octoback 2014-08-25 17:46:04

vous devez utiliser header guard.

mettez ces lignes en haut du fichier d'en-tête

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

et au fond

#endif
2
répondu ntcong 2009-09-03 09:58:46

#pragma once est basé sur le chemin complet du nom de fichier. Donc, ce que vous avez probablement il y a deux copies identiques de Maclasse.H ou Winsock2.h dans différents répertoires.

2
répondu soru 2009-09-03 10:37:56

dans VS 2015, le suivant fonctionnera:

#define _WINSOCKAPI_

alors que ce qui suit ne sera pas:

#define WIN32_LEAN_AND_MEAN
2
répondu MariuszW 2017-05-22 07:23:48

#pragma once est flakey, même sur MS compilateurs, et n'est pas pris en charge par de nombreux autres compilateurs. Comme beaucoup d'autres personnes l'ont mentionné, utiliser include guards est la voie à suivre. N'utilisez pas #pragma once du tout - cela vous facilitera la vie.

1
répondu Thomi 2009-09-03 10:36:00

#include gardes sont le moyen de le faire. #pragma once n'est pas, ce qui signifie que pas tous les compilateurs de soutien.

1
répondu Dima 2009-09-03 10:45:54

dans mon projet (J'utilise VS 2008 SP1) fonctionne solution suivante:

fichier D'en-tête:

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

Rpc classe:

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

où #include " winsock2class.H " classe moyenne qui a mis en œuvre winsock2.h:

//winsock2class.h
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
1
répondu Yahor M 2016-10-31 13:02:49