Como impedir a inclusão de arquivos de cabeçalho duas vezes? O problema é que estou incluindo oem MyClass.h e então eu estou incluindo MyClass.h em muitos arquivos, assim que inclui várias vezes e erro redefinição ocorre. Como prevenir?
Estou usando #pragma uma vez em vez de incluir guardas, e acho que está bem.
MyClass.h:
// MyClass.h
#pragma once
#include <winsock2.h>
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'
c++
header
redefinition
akif
fonte
fonte
Respostas:
Esse problema é causado ao incluir
<windows.h>
antes<winsock2.h>
. Tente organizar sua lista de inclusão<windows.h>
incluída depois<winsock2.h>
ou defina_WINSOCKAPI_
primeiro:Veja também isso .
fonte
<winsock2.h>
com o MSVC2008.<windows.h>
a inclusão gera erros de compilação idênticos aos fornecidos.#include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>
em ordem e estava recebendo winsock2, h arquivo não encontrado. Incluído#define _WINSOCKAPI_
acima de tudo 3 inclui ainda o mesmo erroComo outros sugeriram, o problema é quando
windows.h
é incluído antesWinSock2.h
. Porquewindows.h
incluiwinsock.h
. Você não pode usar ambosWinSock2.h
ewinsock.h
.Soluções:
Incluir
WinSock2.h
anteswindows.h
. No caso de cabeçalhos pré-compilados, você deve resolvê-lo lá. No caso de um projeto simples, é fácil. No entanto, em grandes projetos (especialmente ao escrever código portátil, sem cabeçalhos pré-compilados), pode ser muito difícil, porque quando o cabeçalhoWinSock2.h
está incluído,windows.h
já pode ser incluído em algum outro arquivo de cabeçalho / implementação.Defina
WIN32_LEAN_AND_MEAN
anteswindows.h
ou projete todo. Mas excluirá muitas outras coisas que você pode precisar e deve incluir por conta própria.Defina
_WINSOCKAPI_
anteswindows.h
ou projete todo. Mas quando você inclui,WinSock2.h
recebe um aviso de redefinição de macro.Use em
windows.h
vez deWinSock2.h
quandowinsock.h
é suficiente para o seu projeto (na maioria dos casos, é). Provavelmente, isso resultará em um tempo de compilação mais longo, mas solucionará quaisquer erros / avisos.fonte
WIN32_LEAN_AND_MEAN
foi a solução para mim muitos tanques_WINSOCK_
solução: você não deve grt aviso de redefinição de macro se as duas definições forem idênticas. O erro comum é que as pessoas adicionam definição ao projeto sem definir nenhum valor e esperam uma definição vazia. No entanto, se você adicionar-D_WINSOCK_
à linha cmd, ela será definida_WINSOCK_
como 1. Para criar uma definição vazia,-D_WINSOCK_=
deve ser passada.#define _WINSOCKAPI_
, também poderá precisar#define _WINSOCK_DEPRECATED_NO_WARNINGS
, dependendo das circunstâncias.Ah - a feiura do Windows ... A ordem de inclusões é importante aqui. Você precisa incluir winsock2.h antes do windows.h. Como o windows.h provavelmente está incluído no cabeçalho pré-compilado (stdafx.h), você precisará incluir o winsock2.h a partir daí:
fonte
Usando "protetores de cabeçalho":
fonte
Encontrei este problema ao tentar extrair um pacote de terceiros que aparentemente incluía o windows.h em algum lugar na sua bagunça de cabeçalhos. Definir
_WINSOCKAPI_
no nível do projeto era muito mais fácil (para não mencionar mais sustentável) do que percorrer a sopa e corrigir a inclusão problemática.fonte
DEFINES += _WINSOCKAPI_
No VS 2015, o seguinte funcionará:
Enquanto o seguinte não:
fonte
Eu verifiquei o recursivo inclui, vi os arquivos de cabeçalho que incluem (de forma recursiva) alguns
#include "windows.h"
e#include "Winsock.h"
e escrever um#include "Winsock2.h"
. nesses arquivos, eu adicionei#include "Winsock2.h"
como a primeira inclusão.Apenas uma questão de paciência, observe inclui um por um e estabeleça essa ordem, primeiro e
#include "Winsock2.h"
depois#include "windows.h"
fonte
Encontrei este link windows.he winsock2.h, que tem uma alternativa que funcionou muito bem para mim:
Eu estava tendo problemas para encontrar onde o problema ocorreu, mas adicionando que #define eu era capaz de criar sem descobrir.
fonte
Eu não usaria apenas FILENAME_H, mas
Eu sempre usei um guid postfix. Me deparei com uma base de código muito ruim, alguns anos atrás, que tinha arquivos de cabeçalho diferentes com o mesmo nome de arquivo e incluía guarda. Os arquivos em questão haviam definido uma classe com o mesmo nome. Se apenas namespaces fossem usados. Alguns projetos compilaram outros não. O uso de proteções exclusivas fazia parte da solução na diferenciação de cabeçalhos e seu conteúdo.
No Windows com Visual Studio, use guidgen.exe, no Linux uuidgen -t.
fonte
Corri para o mesmo problema e aqui está o que eu descobri até agora:
Deste fragmento de saída -
-Parece que ws2def.he winsock.h foram incluídos na sua solução.
Se você olhar para o arquivo ws2def.h, ele começará com o seguinte comentário -
Preste atenção na última linha - "Este arquivo não pode ser incluído por um módulo que também inclui o WINSOCK.H"
Ainda tentando corrigir o problema sem fazer alterações no código.
Deixe-me saber se isso faz sentido.
fonte
Você deve usar o protetor de cabeçalho.
coloque essas linhas no topo do arquivo de cabeçalho
e no fundo
fonte
#pragma once
é baseado no caminho completo do nome do arquivo. Portanto, o que você provavelmente tem é que existem duas cópias idênticas do MyClass.h ou Winsock2.h em diretórios diferentes.fonte
#pragma once
é flakey, mesmo em compiladores MS, e não é suportado por muitos outros compiladores. Como muitas outras pessoas mencionaram, usar os protetores de inclusão é o caminho a seguir. Não use#pragma once
nada - isso facilitará sua vida.fonte
#pragma once
, o compilador leva o nome do nó do arquivo de cabeçalho como o ID exclusivo. Isso pode falhar se você tiver links simbólicos ou junções NTFS em sua árvore de origem (mais comuns do que você imagina), ou mesmo se você tiver um arquivo com o mesmo nome em outro diretório de inclusão do sistema (isso já aconteceu comigo antes quando versão 1 e versão 2 da mesma biblioteca instalada em dois caminhos de inclusão diferentes do sistema). Conclusão: para mim, prefiro ter mais controle e conviver com os erros ocasionais de wetware, em vez de confiar em um compilador para fazer isso por mim.#include guardas são a maneira padrão de fazer isso. #pragma uma vez não é, o que significa que nem todos os compiladores o suportam.
fonte
No meu projeto (eu uso o VS 2008 SP1) funciona a próxima solução:
Arquivo de cabeçalho:
Classe Cpp:
onde #include "winsock2class.h" significa a classe que implementou winsock2.h:
fonte
Na verdade, eu tive um problema em que tive que definir o winsock2.h como o primeiro include, parece que ele tem outros problemas com inclusões de outros pacotes. Espero que isso seja útil para alguém que tenha o mesmo problema, não apenas o windows.h, mas tudo incluído.
fonte