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'
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 .
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
avantwindows.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 avecWinSock2.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
avantwindows.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_
avantwindows.h
ou projet large. Mais quand vous incluezWinSock2.h
vous obtenez avertissement de redéfinition macro. -
utilisez
windows.h
au lieu deWinSock2.h
quandwinsock.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.
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
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>
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.
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.
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.
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.
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"
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
#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.
dans VS 2015, le suivant fonctionnera:
#define _WINSOCKAPI_
alors que ce qui suit ne sera pas:
#define WIN32_LEAN_AND_MEAN
#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.
#include gardes sont le moyen de le faire. #pragma once n'est pas, ce qui signifie que pas tous les compilateurs de soutien.
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")