C ++重新定义头文件(winsock2.h)
我如何防止包含头文件两次? 问题是我包括 在MyClass.h中 ,然后我在很多文件中包含了MyClass.h ,所以它包含多次,并且会出现重定义错误。 如何预防?
我使用#pragma而不是包括守卫,我想这很好。
MyClass.h:
// MyClass.h #pragma once #include <winsock2.h> class MyClass { // methods public: MyClass(unsigned short port); virtual ~MyClass(void); };
编辑:几个我得到的错误
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'
在<windows.h>
之前包含<windows.h>
时会导致此问题。 尝试安排<windows.h>
包含在<winsock2.h>
_WINSOCKAPI_
<winsock2.h>
之后的包含列表或首先定义_WINSOCKAPI_
:
#define _WINSOCKAPI_ // stops windows.h including winsock.h #include <windows.h> // ... #include "MyClass.h" // Which includes <winsock2.h>
另见这个 。
正如其他人所build议的,问题是在WinSock2.h
之前包含windows.h
。 因为windows.h
包含winsock.h
。 您不能同时使用WinSock2.h
和winsock.h
。
解决scheme:
-
在
windows.h
之前包含WinSock2.h
。 在预编译头文件的情况下,你应该在那里解决它。 在简单的项目的情况下,很容易。 然而,在大型项目中(特别是在编写可移植代码时,没有预编译头文件)可能会非常困难,因为当包含WinSock2.h
头文件时,windows.h
已经可以从其他头文件/实现文件中包含。 -
在
windows.h
或项目范围之前定义WIN32_LEAN_AND_MEAN
。 但它会排除许多其他你可能需要的东西,你应该把它包括在内。 -
在
windows.h
或项目范围之前定义_WINSOCKAPI_
。 但是,当您包含WinSock2.h
您会收到macros重新定义警告。 -
当
winsock.h
足够用于你的项目时(大多数情况下),使用windows.h
而不是WinSock2.h
。 这可能会导致更长的编译时间,但可以解决任何错误/警告。
通过使用“标题守卫”:
#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
哦 – Windows的丑陋…包括的顺序在这里很重要。 您需要在windows.h之前包含winsock2.h。 由于windows.h可能包含在您的预编译头文件(stdafx.h)中,因此您需要在其中包含winsock2.h:
#include <winsock2.h> #include <windows.h>
我试图拉第三方包,显然包括windows.h在头文件混乱的地方,遇到了这个问题。 在项目层面定义_WINSOCKAPI_
要比通过炖汤和修复问题包括容易得多(更不用说更易于维护)。
我不会只使用FILENAME_H
#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
我一直使用后缀GUID。 几年前,我遇到了一个非常糟糕的代码库,它有不同的头文件,它们具有相同的文件名,并包含警卫。 有问题的文件已经定义了一个具有相同名称的类。 如果只使用命名空间。 有些项目编译没有。 使用独特的警卫是区分标题及其内容的解决scheme的一部分。
在使用Visual Studio的Windows上,在Linux uuidgen -t上使用guidgen.exe。
我发现这个链接windows.h和winsock2.h有一个替代工作伟大的我:
#define _WINSOCKAPI_ // stops windows.h including winsock.h #include <windows.h> #include <winsock2.h>
我很难find问题发生的地方,但是通过添加#define我能够构build而不需要搞清楚。
我遇到了同样的问题,这是我迄今为止发现的:
从这个输出片段 –
c:\ program files \ microsoft sdks \ windows \ v6.0a \ include \ ws2def.h(91):warning C4005:'AF_IPX':macro refinition c:\ program files \ microsoft sdks \ windows \ v6.0a \ include \ winsock.h(460):参见以前定义的'AF_IPX'
– 看起来ws2def.h和winsock.h都已经包含在你的解决scheme中。
如果你看看ws2def.h文件,它会从下面的注释开始 –
/*++ 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 --*/
注意最后一行 – “该文件不能被包含WINSOCK.H的模块包含”
仍然试图纠正这个问题,而不需要修改代码。
让我知道这是否有道理。
你应该使用头文件。
把这些行放在头文件的顶部
#ifndef PATH_FILENAME_H #define PATH_FILENAME_H
并在底部
#endif
#pragma once
是基于文件名的完整path。 所以你可能有两个不同的目录中的MyClass.h或Winsock2.h相同的副本。
#pragma once
是flakey,即使在MS编译器上,也不被许多其他编译器支持。 正如许多人所提到的那样,使用包括守卫者是一条路。 #pragma once
不要使用#pragma once
– 它会让你的生活变得更容易。
#include警卫是这样做的标准方式。 #pragma曾经不是,这意味着并不是所有的编译器都支持它。
我检查了recursion包括,我发现头文件,其中包括(recursion)一些#include "windows.h"
和“#include”Winsock.h“, and write a
#include”Winsock2.h“ . in this files, i added
#include“Winsock2.h”作为第一个包含。
只是一个耐心的问题,看一个一个包含并build立这个命令,首先#include "Winsock2.h"
然后#include "windows.h"
在我的项目(我使用VS 2008 SP1)工作的下一个解决scheme:
头文件:
//myclass.h #pragma once #define _WINSOCKAPI_ #include <windows.h>
Cpp类:
//myclass.cpp #include "Util.h" #include "winsock2class.h" #pragma comment(lib, "Ws2_32.lib")
其中#include“winsock2class.h”是指实现了winsock2.h的类:
//winsock2class.h #include <winsock2.h> #include <windows.h> #pragma comment(lib, "Ws2_32.lib")
在VS 2015中,以下内容将起作用:
#define _WINSOCKAPI_
虽然以下内容不会:
#define WIN32_LEAN_AND_MEAN