156

ヘッダー ファイルを 2 回インクルードしないようにするにはどうすればよいですか? 問題は、私が含めていることですMyClass.hで、その後MyClass.hを多くのファイルにインクルードしているため、複数回インクルードして再定義エラーが発生します。防ぐ方法は?

インクルード ガードの代わりに #pragma once を使用していますが、それで問題ないと思います。

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

16 に答える 16

257

この問題は、<windows.h>beforeを含めるときに発生し<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>

これも参照してください。

于 2009-09-03T11:23:11.393 に答える
82

他の人が示唆したように、問題はいつwindows.hが前に含まれるかWinSock2.hです。windows.hが含まれているためwinsock.hです。WinSock2.hと の両方を使用することはできませんwinsock.h

ソリューション:

  • WinSock2.hの前に含めますwindows.h。プリコンパイル済みヘッダーの場合は、そこで解決する必要があります。単純なプロジェクトの場合は簡単です。WinSock2.hただし、大規模なプロジェクトでは (特に、プリコンパイル済みヘッダーを使用せずに移植可能なコードを作成する場合)、ヘッダーをインクルードwindows.hすると、他のヘッダー/実装ファイルから既にインクルードされている可能性があるため、非常に困難になる可能性があります。

  • WIN32_LEAN_AND_MEANwindows.hまたはプロジェクト全体を定義します。ただし、必要になる可能性のある他の多くのものを除外するため、独自に含める必要があります。

  • _WINSOCKAPI_windows.hまたはプロジェクト全体を定義します。ただし、含めるWinSock2.hと、マクロの再定義の警告が表示されます。

  • プロジェクトにとって十分な場合windows.hの代わりに使用します(ほとんどの場合はそうです)。これにより、コンパイル時間が長くなる可能性がありますが、エラー/警告は解決されます。WinSock2.hwinsock.h

于 2011-11-28T10:47:14.143 に答える
16

ああ、Windows の醜さ...ここではインクルードの順序が重要です。windows.h の前に winsock2.h を含める必要があります。windows.h はおそらくプリコンパイル済みヘッダー (stdafx.h) からインクルードされるため、そこから winsock2.h をインクルードする必要があります。

#include <winsock2.h>
#include <windows.h>
于 2010-07-15T07:24:29.607 に答える
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
于 2009-09-03T09:55:13.553 に答える
7

#include "windows.h"再帰的なインクルードをチェックしたところ、(再帰的に)いくつかをインクルードし#include "Winsock.h"#include "Winsock2.h". このファイルでは、最初のインクルードとして追加#include "Winsock2.h"しました。

辛抱強く、インクルードを 1 つずつ見て、この順序を確立します #include "Winsock2.h"#include "windows.h"

于 2014-08-25T17:46:04.853 に答える
5

このリンクwindows.h と winsock2.hを見つけました。これには、私にとってうまく機能する代替手段があります。

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

問題が発生した場所を見つけるのに苦労しましたが、その #define を追加することで、それを理解することなく構築することができました。

于 2011-04-01T04:02:20.427 に答える
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を使用してきました。私は数年前に、同じファイル名とインクルードガードを持つ異なるヘッダーファイルを持つ非常に貧弱なコードベースに出くわしました。問題のファイルは、同じ名前のクラスを定義していました。名前空間のみが使用された場合。一部のプロジェクトはコンパイルされ、一部はコンパイルされませんでした。一意のガードを使用することは、ヘッダーとその内容を区別するソリューションの一部でした。

Windows と Visual Studio では guidgen.exe を使用し、Linux では uuidgen -t を使用します。

于 2009-09-03T11:45:21.823 に答える
4

同じ問題に遭遇しましたが、これまでに発見したことは次のとおりです。

この出力フラグメントから -

c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(91): 警告 C4005: 'AF_IPX': マクロの再定義
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(460) : '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 を含むモジュールには含めることができません」

コードを変更せずに問題を修正しようとしています。

これが理にかなっているかどうか教えてください。

于 2012-01-09T08:29:09.813 に答える
3

#pragma onceファイル名のフルパスに基づいています。したがって、異なるディレクトリに MyClass.h または Winsock2.h の 2 つの同一のコピーがある可能性があります。

于 2009-09-03T10:37:56.540 に答える
2

ヘッダー ガードを使用する必要があります。

それらの行をヘッダーファイルの先頭に置きます

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

そして一番下に

#endif
于 2009-09-03T09:58:46.337 に答える
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")
于 2016-10-31T12:04:48.953 に答える
1

#pragma onceMS コンパイラでさえ不安定であり、他の多くのコンパイラではサポートされていません。他の多くの人が言及しているように、インクルードガードを使用するのが道です。まったく使用しないでください#pragma once。これにより、生活がずっと楽になります。

于 2009-09-03T10:36:00.773 に答える
1

#include ガードは、これを行う標準的な方法です。 #pragma onceはそうではありません。つまり、すべてのコンパイラがサポートしているわけではありません。

于 2009-09-03T10:45:54.040 に答える