How do I prevent from including header files twice? The problem is I'm including the in MyClass.h and then I'm including MyClass.h in many files, so it includes multiple times and redefinition error occurs. How to prevent?
I'm using #pragma once instead of include guards, and I guess that's fine.
MyClass.h:
// MyClass.h
#pragma once
#include <winsock2.h>
class MyClass
{
// methods
public:
MyClass(unsigned short port);
virtual ~MyClass(void);
};
EDIT: Few of the errors I'm getting
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'
This problem is caused when including <windows.h>
before <winsock2.h>
. Try arrange your include list that <windows.h>
is included after <winsock2.h>
or define _WINSOCKAPI_
first:
#define _WINSOCKAPI_ // stops windows.h including winsock.h
#include <windows.h>
// ...
#include "MyClass.h" // Which includes <winsock2.h>
See also this.
As others suggested, the problem is when windows.h
is included before WinSock2.h
. Because windows.h
includes winsock.h
. You can not use both WinSock2.h
and winsock.h
.
Solutions:
Include
WinSock2.h
beforewindows.h
. In the case of precompiled headers, you should solve it there. In the case of simple project, it is easy. However in big projects (especially when writing portable code, without precompiled headers) it can be very hard, because when your header withWinSock2.h
is included,windows.h
can be already included from some other header/implementation file.Define
WIN32_LEAN_AND_MEAN
beforewindows.h
or project wide. But it will exclude many other stuff you may need and you should include it by your own.Define
_WINSOCKAPI_
beforewindows.h
or project wide. But when you includeWinSock2.h
you get macro redefinition warning.Use
windows.h
instead ofWinSock2.h
whenwinsock.h
is enough for your project (in most cases it is). This will probably result in longer compilation time but solves any errors/warnings.
Oh - the ugliness of Windows... Order of includes are important here. You need to include winsock2.h before windows.h. Since windows.h is probably included from your precompiled header (stdafx.h), you will need to include winsock2.h from there:
#include <winsock2.h>
#include <windows.h>
By using "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
I ran into this problem when trying to pull a third party package which was apparently including windows.h somewhere in it's mess of headers. Defining _WINSOCKAPI_
at the project level was much easier (not to mention more maintainable) than wading through their soup and fixing the problematic include.
In VS 2015, the following will work:
#define _WINSOCKAPI_
While the following won't:
#define WIN32_LEAN_AND_MEAN
I wouldn't use just FILENAME_H but
#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
I have always used a postfix guid. I came across a very poor code base some years ago that had different header files with the same file name and include guard. The files in question had defined a class with the same name. If only namespaces were used. Some projects compiled some didn't. Using unique guards was a part of the solution in differentiating headers and their contents.
On Windows with Visual Studio use guidgen.exe, on Linux uuidgen -t.
I found this link windows.h and winsock2.h which has an alternative that worked great for me:
#define _WINSOCKAPI_ // stops windows.h including winsock.h
#include <windows.h>
#include <winsock2.h>
I was having trouble finding where the issue occurred but by adding that #define I was able to build without figuring it out.
I checked the recursive includes, I spotted the header files which include (recursively) some #include "windows.h"
and "#include "Winsock.h"and write a
#include "Winsock2.h". in this files, i added
#include "Winsock2.h"` as the first include.
Just a matter of patience, look at includes one by one and establish this order, first #include "Winsock2.h"
then #include "windows.h"
I've run into the same issue and here is what I have discovered so far:
From this output fragment -
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'
-It appears that both ws2def.h and winsock.h have been included in your solution.
If you look at the file ws2def.h it starts with the following comment -
/*++
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
--*/
Pay attention to the last line - "This file can not be included by a module that also includes WINSOCK.H"
Still trying to rectify the problem without making changes to the code.
Let me know if this makes sense.
You should use header guard.
put those line at the top of the header file
#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H
and at the bottom
#endif
#pragma once
is based on the full path of the filename. So what you likely have is there are two identical copies of either MyClass.h or Winsock2.h in different directories.
#pragma once
is flakey, even on MS compilers, and is not supported by many other compilers. As many other people have mentioned, using include guards is the way to go. Don't use #pragma once
at all - it'll make your life much easier.
#include guards are the standard way of doing this. #pragma once is not, meaning that not all compilers support it.
In my project (I use VS 2008 SP1) works next solution:
Header file:
//myclass.h
#pragma once
#define _WINSOCKAPI_
#include <windows.h>
Cpp class:
//myclass.cpp
#include "Util.h"
#include "winsock2class.h"
#pragma comment(lib, "Ws2_32.lib")
where #include "winsock2class.h" mean class which implemented winsock2.h :
//winsock2class.h
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
I actually ran into an issue where I had to define winsock2.h as the first include, it seems it has other issues with includes from other packages. Hope this is helpful to someone who runs into same issue, not just windows.h but all includes.
来源:https://stackoverflow.com/questions/1372480/c-redefinition-header-files-winsock2-h