Arquivos de header de redefinição de C ++ (winsock2.h)

Como evito include arquivos de header duas vezes? O problema é que eu estou incluindo o em MyClass.h e, em seguida, estou incluindo MyClass.h em muitos arquivos, por isso inclui várias vezes e erro de redefinição ocorre. Como prevenir?

Eu estou usando # pragma uma vez em vez de include guardas, e acho que está tudo bem.

MyClass.h:

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

EDIT: alguns dos erros que estou recebendo

 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' 

Esse problema é causado ao include antes de . Tente organizar sua lista de inclusão que é incluída após ou defina _WINSOCKAPI_ primeiro:

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

Veja também isso .

Como outros sugeriram, o problema é quando o windows.h é incluído antes do WinSock2.h . Porque windows.h inclui winsock.h . Você não pode usar o WinSock2.h e winsock.h .

Soluções:

  • Inclua WinSock2.h antes do windows.h . No caso de headers pré-compilados, você deve resolvê-lo lá. No caso de projeto simples, é fácil. No entanto, em grandes projetos (especialmente ao escrever código portátil, sem headers pré-compilados) pode ser muito difícil, porque quando o header com WinSock2.h é incluído, o windows.h já pode estar incluído em algum outro arquivo de header / implementação.

  • Defina WIN32_LEAN_AND_MEAN antes do windows.h ou do projeto WIN32_LEAN_AND_MEAN . Mas excluirá muitas outras coisas que você pode precisar e você deve incluí-las por conta própria.

  • Defina _WINSOCKAPI_ antes do windows.h ou do projeto _WINSOCKAPI_ . Mas quando você inclui WinSock2.h você recebe aviso de redefinição de macro.

  • Use windows.h vez de WinSock2.h quando winsock.h é suficiente para o seu projeto (na maioria dos casos é). Isso provavelmente resultará em mais tempo de compilation, mas resolverá erros / avisos.

Usando “guardas de header”:

 #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 – a fealdade do Windows … A ordem das inclusões é importante aqui. Você precisa include o winsock2.h antes do windows.h. Como o windows.h provavelmente está incluído no seu header pré-compilado (stdafx.h), você precisará include o winsock2.h de lá:

 #include  #include  

Eu corri para este problema ao tentar puxar um pacote de terceiros que aparentemente estava incluindo windows.h em algum lugar na bagunça de headers. Definir _WINSOCKAPI_ no nível do projeto era muito mais fácil (para não mencionar mais sustentável) do que vasculhar sua sopa e consertar a problemática include.

Eu não usaria apenas FILENAME_H, mas

 #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 

Eu sempre usei um postfix guid. Me deparei com uma base de código muito pobre há alguns anos que tinha arquivos de header diferentes com o mesmo nome de arquivo e incluía guarda. Os arquivos em questão definiram uma class com o mesmo nome. Se apenas namespaces foram usados. Alguns projetos compilados alguns não. A utilização de proteções únicas fazia parte da solução na diferenciação de headers e seu conteúdo.

No Windows com o Visual Studio, use o guidgen.exe, no Linux uuidgen -t.

Eu encontrei este link windows.h e winsock2.h que tem uma alternativa que funcionou muito bem para mim:

 #define _WINSOCKAPI_ // stops windows.h including winsock.h #include  #include  

Eu estava tendo problemas para encontrar onde o problema ocorreu, mas adicionando que #define eu era capaz de construir sem descobrir.

Eu me deparei com o mesmo problema e aqui está o que eu descobri até agora:

Deste fragment de saída –

 c: \ Arquivos de Programas \ Microsoft sdks \ windows \ v6.0a \ include \ ws2def.h (91): aviso C4005: 'AF_IPX': redefinição de macro
 c: \ Arquivos de Programas \ Microsoft sdks \ windows \ v6.0a \ include \ winsock.h (460): veja a definição anterior de 'AF_IPX'

-Parece que ws2def.h e winsock.h foram incluídos na sua solução.

Se você olhar para o arquivo ws2def.h, ele começa com o seguinte comentário –

 /*++ 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 --*/ 

Preste atenção na última linha – “Este arquivo não pode ser incluído por um módulo que também inclua WINSOCK.H”

Ainda tentando corrigir o problema sem fazer alterações no código.

Deixe-me saber se isso faz sentido.

Eu verifiquei o recursivo inclui, vi os arquivos de header que incluem (recursivamente) alguns #include "windows.h" e “# include” Winsock.h ” and write a #include” Winsock2.h ” . in this files, i added Nesses . in this files, i added #include “Winsock2.h” `como o primeiro include.

Apenas uma questão de paciência, olhe para include um por um e estabelecer essa ordem, primeiro #include "Winsock2.h" depois #include "windows.h"

Você deve usar o protetor de header.

coloque essa linha no topo do arquivo de header

 #ifndef PATH_FILENAME_H #define PATH_FILENAME_H 

e na parte inferior

 #endif 

#pragma once é baseado no caminho completo do nome do arquivo. Então, o que você provavelmente tem é que existem duas cópias idênticas de MyClass.h ou Winsock2.h em diretórios diferentes.

No VS 2015, o seguinte irá funcionar:

 #define _WINSOCKAPI_ 

Enquanto o seguinte não:

 #define WIN32_LEAN_AND_MEAN 

#pragma once é flakey, mesmo em compiladores MS, e não é suportado por muitos outros compiladores. Como muitas outras pessoas mencionaram, o uso de guardas é o caminho a percorrer. Não use #pragma once – isso tornará sua vida muito mais fácil.

Guardas #include são a maneira padrão de se fazer isso. #pragma uma vez não é, o que significa que nem todos os compiladores suportam isso.

No meu projeto (eu uso o VS 2008 SP1) funciona a próxima solução:

Arquivo de header:

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

Classe Cpp:

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

onde #include “winsock2class.h” significa class que implementou winsock2.h:

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