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

时间:2009-09-03 09:53:27

标签: c++ header redefinition

如何阻止两次包含头文件?问题是我在 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'

16 个答案:

答案 0 :(得分:208)

<windows.h>之前加入<winsock2.h>时会导致此问题。请尝试安排<windows.h>之后包含<winsock2.h>或首先定义_WINSOCKAPI_的包含列表:

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

另见this

答案 1 :(得分:71)

正如其他人所说,问题是在windows.h之前包含WinSock2.h的时间。因为windows.h包含winsock.h。您不能同时使用WinSock2.hwinsock.h

解决方案:

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

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

  • _WINSOCKAPI_或项目范围之前定义windows.h。但是,当您加入WinSock2.h时,您会收到宏重新定义警告。

  • windows.h足够您的项目时(在大多数情况下),使用WinSock2.h代替winsock.h。这可能会导致更长的编译时间,但可以解决任何错误/警告。

答案 2 :(得分:14)

使用“标题保护”:

#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

答案 3 :(得分:13)

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

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

答案 4 :(得分:6)

当我试图拉出第三方软件包时,我遇到了这个问题,这个软件包显然包含了windows.h中的某些内容。在项目层面定义_WINSOCKAPI_比趟过他们的汤并修复有问题的包括更容易(更不用说更易于维护)。

答案 5 :(得分:5)

在VS 2015中,以下内容将起作用:

#define _WINSOCKAPI_

以下情况不会:

#define WIN32_LEAN_AND_MEAN

答案 6 :(得分:4)

我不会只使用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。几年前我遇到了一个非常糟糕的代码库,它有不同的头文件,文件名相同,包含guard。有问题的文件定义了一个具有相同名称的类。如果仅使用名称空间。有些项目编成的一些没有。使用独特的防护是区分标题及其内容的解决方案的一部分。

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

答案 7 :(得分:4)

我发现这个链接windows.h and winsock2.h有一个对我有用的替代方案:

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

我无法找到问题发生的位置但是通过添加#define我能够构建而无需弄清楚。

答案 8 :(得分:3)

我遇到了同样的问题,这是我到目前为止所发现的:

从此输出片段 -

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的模块不能包含此文件”

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

如果这是有道理的,请告诉我。

答案 9 :(得分:3)

我检查了递归包含,我发现了包含(递归)某些#include "windows.h"和“#include”Winsock.h的头文件。“and write a #include”Winsock2.h“{{1} } #include“Winsock2.h”`作为第一个包含。

只需耐心,请逐个查看并确定此订单,先. in this files, i added然后#include "Winsock2.h"

答案 10 :(得分:2)

你应该使用标题保护。

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

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

并在底部

#endif

答案 11 :(得分:2)

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

答案 12 :(得分:1)

#pragma once即使在MS编译器上也是如此,许多其他编译器都不支持它。正如许多其他人所提到的那样,使用包含警卫是可行的方法。不要使用#pragma once - 它会让你的生活更轻松。

答案 13 :(得分:1)

#include guards是执行此操作的标准方法。 #pragma once不是,意味着并非所有编译器都支持它。

答案 14 :(得分:1)

在我的项目中(我使用VS 2008 SP1)可以使用下一个解决方案:

标题文件:

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

答案 15 :(得分:0)

我实际上遇到了一个问题,即我必须将winsock2.h定义为第一个include,看来其他软件包的include也存在其他问题。希望这对遇到同样问题的人有所帮助,不仅是windows.h,还包括所有问题。