C + + 重定义头文件(winsock2.h)

如何防止包含头文件两次?问题是我在 MyClass.h中包含了 ,然后我在很多文件中包含了 MyClass.h,所以它包含了很多次,并且会出现重定义错误。如何预防?

我使用了一次 # 杂注,而不是加入警卫,我想这没什么问题。

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'
162483 次浏览

您应该使用头部防护。

把这些行放在头文件的顶部

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

在底部

#endif

#pragma once非常奇怪,即使在 MS 编译器上也是如此,而且许多其他编译器都不支持 #pragma once。正如许多其他人所提到的,使用 include 警卫是正确的做法。根本不要使用 #pragma once-它会使你的生活更容易。

#pragma once基于文件名的完整路径。所以你可能有两个完全相同的 MyClass.h 或 Winsock2.h 的副本在不同的目录中。

这个问题是在 <winsock2.h>之前包含 <windows.h>时引起的。尝试安排你的包含列表,<windows.h>包含在 <winsock2.h>之后,或者首先定义 _WINSOCKAPI_:

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

参见 这个

我不会只使用 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

我一直使用后缀帮助。几年前,我遇到过一个非常糟糕的代码库,它有不同的头文件,文件名相同,包含 Guard。有问题的文件定义了一个具有相同名称的类。如果只使用名称空间。一些项目编译了一些没有。使用独特的保护是区分标头及其内容的解决方案的一部分。

在 Windows 和 Visual Studio 上使用 guidgen.exe,在 Linux uuidgen-t 上使用。

当我试图拉取一个第三方软件包时,我遇到了这个问题,这个软件包显然包含了 windows.h,它的标题很混乱。在项目级别定义 _WINSOCKAPI_要比费力地处理问题和修复有问题的 include 容易得多(更不用说更易于维护)。

哦-窗户的丑陋... 包含顺序在这里很重要。您需要在 windows.h 之前包含 winsock2.h。由于 windows.h 可能包含在你的预编译头中(stdafx.h) ,所以你需要包含 winsock2.h:

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

我发现了这个链接 Windows.h 和 Winsock2.h,它有一个替代品,对我来说非常有效:

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

我很难找到问题发生的地方,但是通过添加 # Definition,我可以在没有找到问题所在的情况下构建它。

正如其他人所建议的那样,问题在于 windows.hWinSock2.h之前被包括在内。因为 windows.h包括 winsock.h。不能同时使用 WinSock2.hwinsock.h

解决方案:

  • windows.h之前包括 WinSock2.h。在预编译头的情况下,您应该在那里解决它。在简单项目的情况下,它是容易的。然而,在大型项目中(特别是在编写没有预编译头的可移植代码时) ,这可能非常困难,因为当包含 WinSock2.h的头文件时,windows.h可能已经包含在其他一些头文件/实现文件中。

  • windows.h或项目范围之前定义 WIN32_LEAN_AND_MEAN。但它会排除许多其他你可能需要的东西,你应该包括自己的。

  • windows.h或者项目之前定义 _WINSOCKAPI_。但是当你包含 WinSock2.h时,你会得到宏重定义的警告。

  • winsock.h对于您的项目来说已经足够时,使用 windows.h而不是 WinSock2.h(在大多数情况下是这样)。这可能会导致较长的编译时间,但可以解决任何错误/警告。

我也遇到过同样的问题,以下是我目前为止的发现:

从这个输出片段-

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'

- 看起来 ws2def.h 和 winsock.h 都包含在您的解决方案中。

如果您查看文件 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 的模块中”

仍然试图在不更改代码的情况下纠正问题。

让我知道这是否有意义。

我检查了递归包括,我发现头文件包括(递归)一些 #include "windows.h"#include "Winsock.h"和写一个 #include "Winsock2.h"。在这个文件中,我添加了 #include "Winsock2.h"作为第一个 include。

只是耐心的问题,看包括一个接一个,建立这个秩序,首先 #include "Winsock2.h"然后 #include "windows.h"

在我的项目中(我使用 VS2008SP1)下一个解决方案:

头文件:

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

课程类别:

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

我实际上遇到了一个问题,我必须将 winsock2.h 定义为第一个 include,它似乎与其他包中的 include 有其他问题。希望这对遇到同样问题的人有所帮助,不仅仅是 windows.h,而是包括所有问题。