cpp and c++ header redefinition

c++ - class h and class cpp



Archivos de encabezado de redefinición de C++(winsock2.h) (15)

Ah, la fealdad de Windows ... El orden de los incluidos 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í:

#include <winsock2.h> #include <windows.h>

¿Cómo evito incluir archivos de encabezado dos veces? El problema es que estoy incluyendo el en 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 vez 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: Algunos de los errores que obtengo

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''


Al usar "guardias de encabezado":

#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


Como otros sugirieron, el problema es cuando se incluye windows.h antes de WinSock2.h . Porque windows.h incluye winsock.h . No puede usar tanto WinSock2.h winsock.h .

Soluciones:

  • Incluya WinSock2.h antes de windows.h . En el caso de encabezados precompilados, debe resolverlo allí. En el caso del proyecto simple, es fácil. Sin embargo, en proyectos grandes (especialmente cuando se escribe código portátil, sin encabezados precompilados) puede ser muy difícil, porque cuando se incluye su encabezado con WinSock2.h , windows.h ya puede estar incluido desde algún otro archivo de cabecera / implementación.

  • Defina WIN32_LEAN_AND_MEAN antes de windows.h o proyecto de ancho. Pero excluirá muchas otras cosas que pueda necesitar y debe incluirlas por su cuenta.

  • Defina _WINSOCKAPI_ antes de windows.h o proyecto de ancho. Pero cuando incluye WinSock2.h obtiene una advertencia de redefinición de macros.

  • Use windows.h lugar de WinSock2.h cuando winsock.h sea ​​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.


Debe usar protector de encabezado.

poner esas líneas en la parte superior del archivo de encabezado

#ifndef PATH_FILENAME_H #define PATH_FILENAME_H

y en la parte inferior

#endif


En VS 2015, lo siguiente funcionará:

#define _WINSOCKAPI_

Mientras que lo siguiente no:

#define WIN32_LEAN_AND_MEAN


En mi proyecto (uso VS 2008 SP1) funciona la siguiente solución:

Archivo de cabecera:

//myclass.h #pragma once #define _WINSOCKAPI_ #include <windows.h>

Clase Cpp:

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

donde #include "winsock2class.h" significa clase que implementó winsock2.h:

//winsock2class.h #include <winsock2.h> #include <windows.h> #pragma comment(lib, "Ws2_32.lib")


Encontré este enlace this que tiene una alternativa que me fue muy this :

#define _WINSOCKAPI_ // stops windows.h including winsock.h #include <windows.h> #include <winsock2.h>

Estaba teniendo problemas para encontrar dónde ocurrió el problema, pero al agregar que #define pude construir sin resolverlo.


Este problema se produce cuando se incluye <windows.h> antes de <winsock2.h> . Intente organizar su lista de inclusión que <windows.h> se incluye después de <winsock2.h> o defina _WINSOCKAPI_ primero:

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

Ver también this


Me encontré con el mismo problema y aquí está lo que he descubierto hasta ahora:

De este fragmento de salida -

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''

- Parece que tanto ws2def.h como winsock.h han sido incluidos en su solución.

Si miras el archivo ws2def.h, comienza con el siguiente comentario:

/*++ 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 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 estoy tratando de rectificar el problema sin hacer cambios en el código.

Avísame si esto tiene sentido.


Me encontré con este problema cuando traté de extraer un paquete de un tercero que aparentemente incluía Windows.h en algún lugar en su desorden de encabezados. Definir _WINSOCKAPI_ a nivel de proyecto fue mucho más fácil (por no mencionar que más fácil de mantener) que vadear su sopa y solucionar la problemática incluyen.


No usaría solo FILENAME_H, pero

#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

Siempre he usado una guía de postfix. Encontré 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 guard. Los archivos en cuestión habían definido una clase con el mismo nombre. Si solo se usaran espacios de nombres. Algunos proyectos compilados algunos no lo hicieron. El uso de guardias únicos fue parte de la solución al diferenciar los encabezados y sus contenidos.

En Windows con Visual Studio use guidgen.exe, en Linux uuidgen -t.


Revisé el recursivo incluye, vi los archivos de encabezado que incluyen (recursivamente) algunos #include "windows.h" y "#include" Winsock.h " and write a #include" Winsock2.h " . in this files, i added #include "Winsock2.h" `como el primer include.

Solo una cuestión de paciencia, mira incluye uno por uno y establece este orden, primero #include "Winsock2.h" luego #include "windows.h"



#pragma once es escaso, 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 uses #pragma once , te hará la vida mucho más fácil.


#pragma once se basa en la ruta completa del nombre de archivo. Entonces, lo que probablemente tenga es que hay dos copias idénticas de MyClass.ho Winsock2.h en directorios diferentes.