¿Cómo evito incluir archivos de encabezado dos veces? El problema es que incluyo elen MyClass.h y luego incluyo MyClass.h en muchos archivos, por lo que incluye varias veces y se produce un error de redefinición. ¿Como prevenir?
Estoy usando #pragma una vez en lugar de incluir guardias, y supongo que está bien.
MyClass.h:
// MyClass.h
#pragma once
#include <winsock2.h>
class MyClass
{
// methods
public:
MyClass(unsigned short port);
virtual ~MyClass(void);
};
EDITAR: Pocos de los errores que estoy recibiendo
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
fuente
fuente
Respuestas:
Este problema es causado cuando se incluye
<windows.h>
antes<winsock2.h>
. Intente organizar su lista de inclusión que<windows.h>
se incluye después<winsock2.h>
o defina_WINSOCKAPI_
primero:Ver también esto .
fuente
<winsock2.h>
en MSVC2008.<windows.h>
la inclusión hace que genere errores de compilación idénticos a los que usted proporcionó.#include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>
en orden y estaba obteniendo el archivo winsock2, h no encontrado. Incluido#define _WINSOCKAPI_
por encima de los 3 incluye aún el mismo errorComo otros sugirieron, el problema es cuando
windows.h
se incluye antesWinSock2.h
. Porquewindows.h
incluyewinsock.h
. No puedes usar ambosWinSock2.h
ywinsock.h
.Soluciones:
Incluir
WinSock2.h
anteswindows.h
. En el caso de encabezados precompilados, debe resolverlo allí. En el caso de un proyecto simple, es fácil. Sin embargo, en grandes proyectos (especialmente cuando se escribe código portátil, sin encabezados precompilados) puede ser muy difícil, porque cuandoWinSock2.h
se incluye su encabezado con ,windows.h
ya se puede incluir desde algún otro archivo de encabezado / implementación.Definir
WIN32_LEAN_AND_MEAN
anteswindows.h
o proyectar todo. Pero excluirá muchas otras cosas que pueda necesitar y debe incluirlas usted mismo.Definir
_WINSOCKAPI_
anteswindows.h
o proyectar todo. Pero cuando lo incluyeWinSock2.h
, obtiene una advertencia de redefinición de macros.Use en
windows.h
lugar deWinSock2.h
cuándowinsock.h
es suficiente para su proyecto (en la mayoría de los casos lo es). Esto probablemente dará como resultado un tiempo de compilación más largo, pero resuelve cualquier error / advertencia.fuente
WIN32_LEAN_AND_MEAN
era la solución para los tanques de mí mucho_WINSOCK_
solución: no debe obtener una advertencia de redefinición de macros si ambas definiciones son idénticas. El error común es que las personas agregan definición al proyecto sin establecer ningún valor y esperan una definición vacía. Sin embargo, si agrega-D_WINSOCK_
a la línea cmd, se establecerá_WINSOCK_
en 1. Para crear una definición vacía, se-D_WINSOCK_=
debe pasar.#define _WINSOCKAPI_
, también puede necesitar#define _WINSOCK_DEPRECATED_NO_WARNINGS
, dependiendo de sus circunstancias.Oh, la fealdad de Windows ... El orden de inclusión es importante aquí. Debe incluir winsock2.h antes de windows.h. Dado que windows.h probablemente se incluye desde su encabezado precompilado (stdafx.h), deberá incluir winsock2.h desde allí:
fuente
Mediante el uso de "protectores de encabezado":
fuente
Me encontré con este problema al intentar extraer un paquete de terceros que aparentemente incluía windows.h en algún lugar de su lío de encabezados. Definir
_WINSOCKAPI_
a nivel de proyecto fue mucho más fácil (sin mencionar que es más fácil de mantener) que vadear su sopa y arreglar la inclusión problemática.fuente
DEFINES += _WINSOCKAPI_
En VS 2015, lo siguiente funcionará:
Si bien lo siguiente no lo hará:
fuente
Comprobé el recursiva incluye, vi a los ficheros de cabecera que incluyen (de forma recursiva) alguna
#include "windows.h"
y#include "Winsock.h"
y escribir una#include "Winsock2.h"
. en estos archivos, agregué#include "Winsock2.h"
como la primera inclusión.Solo es cuestión de paciencia, mira incluye uno por uno y establece este orden, primero
#include "Winsock2.h"
luego#include "windows.h"
fuente
Encontré este enlace windows.h y winsock2.h que tiene una alternativa que funcionó muy bien para mí:
Estaba teniendo problemas para encontrar dónde ocurrió el problema, pero al agregar que #define pude construir sin descubrirlo.
fuente
No usaría solo FILENAME_H pero
Siempre he usado un postfix guid. Me encontré con una base de código muy pobre hace algunos años que tenía diferentes archivos de encabezado con el mismo nombre de archivo e incluye guardia. Los archivos en cuestión habían definido una clase con el mismo nombre. Si solo se usaran espacios de nombres. Algunos proyectos compilados otros no. El uso de guardias únicos era parte de la solución para diferenciar los encabezados y sus contenidos.
En Windows con Visual Studio, use guidgen.exe, en Linux uuidgen -t.
fuente
Me he encontrado con el mismo problema y esto es lo que he descubierto hasta ahora:
De este fragmento de salida:
-Parece que tanto ws2def.h como winsock.h se han incluido en su solución.
Si observa el archivo ws2def.h, comienza con el siguiente comentario:
Preste atención a la última línea: "Este archivo no puede ser incluido por un módulo que también incluya WINSOCK.H"
Todavía trato de corregir el problema sin hacer cambios en el código.
Avísame si esto tiene sentido.
fuente
Deberías usar el protector de cabecera.
poner esas líneas en la parte superior del archivo de encabezado
y en la parte inferior
fuente
#pragma once
se basa en la ruta completa del nombre del archivo. Entonces, lo que probablemente tenga es que hay dos copias idénticas de MyClass.h o Winsock2.h en diferentes directorios.fuente
#pragma once
es flakey, incluso en compiladores de MS, y no es compatible con muchos otros compiladores. Como muchas otras personas han mencionado, usar incluir guardias es el camino a seguir. No lo uses#pragma once
en absoluto: te hará la vida mucho más fácil.fuente
#pragma once
, el compilador toma el nombre del nodo del archivo de encabezado como ID único. Esto puede fallar si tiene enlaces simbólicos o uniones NTFS en su árbol de origen (más común de lo que podría pensar), o incluso si tiene un archivo del mismo nombre en otro directorio de inclusión del sistema (esto me ha sucedido antes cuando tenía la versión 1 y la versión 2 de la misma biblioteca instalada en dos sistemas diferentes incluyen rutas). En pocas palabras: para mí, prefiero tener más control y vivir con el error ocasional del software, en lugar de confiar en un compilador para que lo haga por mí.# incluir guardias son la forma estándar de hacer esto. #pragma una vez no lo es, lo que significa que no todos los compiladores lo admiten.
fuente
En mi proyecto (uso VS 2008 SP1) funciona la siguiente solución:
Archivo de cabecera:
Clase cpp:
donde #include "winsock2class.h" clase media que implementó winsock2.h:
fuente
En realidad, me encontré con un problema en el que tenía que definir winsock2.h como la primera inclusión, parece tener otros problemas con las inclusiones de otros paquetes. Espero que esto sea útil para alguien que tenga el mismo problema, no solo windows.h, sino todo incluido.
fuente