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

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

J’utilise #pragma une fois au lieu d’inclure des gardes, et je suppose que ça va.

MyClass.h:

// MyClass.h #pragma once #include  class MyClass { // methods public: MyClass(unsigned short port); virtual ~MyClass(void); }; 

EDIT: Peu des erreurs que je reçois

 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' 

Ce problème est dû à l’inclusion de avant . Essayez d’organiser votre liste d’inclusions que est incluse après ou définissez d’abord _WINSOCKAPI_ :

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

Voir aussi ceci .

Comme d’autres l’ont suggéré, le problème est que 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 devriez le résoudre ici. Dans le cas d’un projet simple, c’est facile. Cependant, dans les grands projets (en particulier lors de l’écriture de code portable, sans en-têtes précompilés), cela peut être très difficile, car lorsque votre en-tête avec WinSock2.h est inclus, windows.h peut déjà être inclus dans un autre fichier d’en-tête / implémentation.

  • Définissez WIN32_LEAN_AND_MEAN avant windows.h ou à l’échelle du projet. Mais cela exclura beaucoup d’autres choses dont vous pourriez avoir besoin et que vous devriez inclure vous-même.

  • Définissez _WINSOCKAPI_ avant windows.h ou à l’échelle du projet. Mais lorsque vous incluez WinSock2.h vous obtenez un avertissement de redéfinition de macro.

  • Utilisez windows.h au lieu de WinSock2.h quand winsock.h est suffisant pour votre projet (dans la plupart des cas). Cela entraînera probablement un temps de compilation plus long mais résout les erreurs / avertissements.

En utilisant “header guards”:

 #ifndef MYCLASS_H #define MYCLASS_H // This is unnecessary, see comments. //#pragma once // MyClass.h #include  class MyClass { // methods public: MyClass(unsigned short port); virtual ~MyClass(void); }; #endif 

Oh – la laideur de Windows … L’ordre des inclus est important ici. Vous devez inclure winsock2.h avant windows.h. Comme windows.h est probablement inclus dans votre en-tête précompilé (stdafx.h), vous devrez inclure winsock2.h à partir de là:

 #include  #include  

J’ai rencontré ce problème en essayant d’extraire un paquet tiers qui incluait apparemment Windows.h quelque part dans son bourrage d’en-têtes. Définir _WINSOCKAPI_ au niveau du projet était beaucoup plus facile (pour ne pas dire plus facile à maintenir) que de parcourir leur soupe et de résoudre le problème.

Je n’utiliserais pas seulement 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é un guide postfix. Il y a quelques années, je suis tombé sur une très mauvaise base de code qui contenait des fichiers d’en-tête différents avec le même nom de fichier et incluait un garde. Les fichiers en question avaient défini une classe du même nom. Si seuls les espaces de noms ont été utilisés. Certains projets compilés en ont pas. L’utilisation de gardes uniques faisait partie de la solution pour différencier les en-têtes et leur contenu.

Sous Windows avec Visual Studio, utilisez guidgen.exe, sous Linux uuidgen -t.

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  #include  

J’avais du mal à trouver où le problème était survenu mais en ajoutant cette #define que je pouvais construire sans le savoir.

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: \ programmes \ microsoft sdks \ windows \ v6.0a \ include \ ws2def.h (91): avertissement C4005: 'AF_IPX': redéfinition de la macro
 c: \ programmes \ microsoft sdks \ windows \ v6.0a \ include \ winsock.h (460): voir la définition précédente de 'AF_IPX'

-Il semble que 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 --*/ 

Faites attention à la dernière ligne – “Ce fichier ne peut pas être inclus par un module qui inclut également WINSOCK.H”

Toujours en train de rectifier le problème sans apporter de modifications au code.

Faites-moi savoir si cela a du sens.

J’ai vérifié les inclusions récursives, j’ai repéré les fichiers d’en-tête qui incluent (récursivement) certains #include "windows.h" et “#include” Winsock.h ” and write a #include” Winsock2.h ” . in this files, i added #include “Winsock2.h” `comme le premier inclut.

Juste une question de patience, regardez un par un et établissez cet ordre, d’abord #include "Winsock2.h" puis #include "windows.h"

Vous devez utiliser un protège-en-tête.

mettre ces lignes en haut du fichier d’en-tête

 #ifndef PATH_FILENAME_H #define PATH_FILENAME_H 

et en bas

 #endif 

#pragma once est basé sur le chemin complet du nom de fichier. Donc, vous avez probablement deux copies identiques de MyClass.h ou Winsock2.h dans des répertoires différents.

Dans VS 2015, les éléments suivants fonctionneront:

 #define _WINSOCKAPI_ 

Alors que les suivants ne seront pas:

 #define WIN32_LEAN_AND_MEAN 

#pragma once est flou, même sur les compilateurs MS, et n’est pas supporté par beaucoup d’autres compilateurs. Comme beaucoup d’autres personnes l’ont mentionné, l’utilisation d’incluants est la voie à suivre. N’utilisez pas #pragma once – cela vous facilitera la vie.

#include les gardes sont la manière standard de le faire. #pragma une fois n’est pas, ce qui signifie que tous les compilateurs ne le supportent pas.

Dans mon projet (j’utilise VS 2008 SP1) fonctionne la solution suivante:

header de fichier:

 //myclass.h #pragma once #define _WINSOCKAPI_ #include  

Classe Cpp:

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

où #include “winsock2class.h” signifie classe qui implémente winsock2.h:

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