C ++再定義ヘッダーファイル(winsock2.h)


143

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

インクルードガードの代わりに#pragmaを1回使用していますが、それで問題ありません。

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
#pragmaはすでに1回使用しているため、1回だけ含める必要があります。
ナビーン

1
コンパイラはプラグマを一度サポートしていませんか?
Svetlozar Angelov

Visual Studio 2008を使用していますが、<winsock2.h>が2回含まれているのはなぜですか?
akif 2009

1
MyClass.hのインクルードヘッダーの一部から2回インクルードされる可能性があります
Svetlozar Angelov

5
winsock2とwinsockの構造は共通しています。両方ではなく、1つだけを含める必要があります
Svetlozar Angelov

回答:


234

この問題は、<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>

参照してくださいこれを


<windows.h>はまったく含めていませんが、<winsock2.h>がそれを実行することはわかっています。
akif 2009

2
私にとってあなたのコード<winsock2.h>はMSVC2008 でのみコンパイルできます。<windows.h>含めると、指定したのと同じコンパイルエラーが生成されます。
pingw33n 2009

<windows.h>はstdafx.hに含まれていますか?
Colin Desmond、

1
このソリューションで、VS 2010とSDK 7.1で問題が解決しました。pingw33nありがとうございます!
アダムフィスク2011

私は#include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>順番に持っていて、winsock2、hファイルが見つかりませんでした。付属#define _WINSOCKAPI_ のすべての3の上方には、まだ同じエラーが含まれて
エヴァ

75

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

ソリューション:

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

  • WIN32_LEAN_AND_MEAN前に定義するwindows.hか、プロジェクト全体に適用します。しかし、それはあなたが必要とするかもしれない他の多くのものを除外し、あなた自身でそれを含めるべきです。

  • _WINSOCKAPI_前に定義するwindows.hか、プロジェクト全体に適用します。ただし、含めるWinSock2.hと、マクロの再定義の警告が表示されます。

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


14
WIN32_LEAN_AND_MEAN私の戦車の多くの解決策でした
ジョナタンクルティエ2012年

_WINSOCK_解決策について:両方の定義が同一である場合は、マクロ再定義警告をgrtしないでください。一般的なバグは、人々が値を設定せずにプロジェクトに定義を追加し、空の定義を期待することです。ただし、-D_WINSOCK_cmd行に追加すると_WINSOCK_、1に設定されます。空の定義を作成するに-D_WINSOCK_=は、渡す必要があります。
パヴェルStankowski

を使用する場合、状況によって#define _WINSOCKAPI_はも必要#define _WINSOCK_DEPRECATED_NO_WARNINGSになる場合があります。
Lorien Brune

16

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

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

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

2
私は間違っていると思います(現時点では4票)が、インクルードガードの使用はプラグマと同じであると思います。
Svetlozar Angelov

1
まあ、私は#pragmaを一度持っていますが、これは同じヘッダーガードです
akif

2
@アンゲロフ:はい、それは彼らが同じものだと私が言っていることです。問題は私のヘッダーファイルにはありませんが、<winsock2.h>自体にはヘッダーガードがないか、他の何かである可能性があると思います。
akif

1
定義により、#pragmaはコンパイラーに依存します(非標準)。すべてのコンパイラで機能するとは限りません。ビジュアルスタジオが#pargmaを一度受け入れることを知っています。gccがそうかどうかはわかりません。警備員を含めると常に機能することは知っています。私は#pragmaを1回だけ使用し、最大限の収益性を得るためにガードを含めます。MSVCは#pragmaの処理を1回最適化し、gccはincludeガードの処理を最適化しているようです。標準ヘッダーとの唯一の違いは、#pragaがincludeガードの外にあることです。
KitsuneYMG 2009

1
「#pragma」コマンドは、ANSI規格で指定されており、任意の実装定義の効果をもたらします。GNU Cプリプロセッサでは、「#pragma」はまずゲーム「ローグ」を実行しようとします。それが失敗した場合、ゲーム「ハック」を実行しようとします。それが失敗した場合、ハノイの塔を表示するGNU Emacsを実行しようとします。それが失敗すると、致命的なエラーが報告されます。いずれの場合も、前処理は続行されません。
-Richard

6

ヘッダーの混乱のどこかにwindows.hが含まれているように見えるサードパーティのパッケージをプルしようとしたときに、この問題に遭遇しました。_WINSOCKAPI_プロジェクトレベルでの定義は、それらのスープを調べて問題のあるインクルードを修正するよりもはるかに簡単です(保守性は言うまでもありません)。


1
:Qtの上、.PROファイルで、それはこのようになります DEFINES += _WINSOCKAPI_
phyatt

@phyatt:私がそうしないなら、あなたはそれを答えに変えるべきです!
Leif Gruenwoldt、2015

@LeifGruenwoldt頑張ってね!お役に立てて嬉しいです。
フィアット2015

6

VS 2015では、以下が機能します。

#define _WINSOCKAPI_

ただし、次のことはできません。

#define WIN32_LEAN_AND_MEAN

6

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

忍耐の問題ですが、1つずつインクルードを見て、この順序を確立してから、最初 #include "Winsock2.h"#include "windows.h"


5

私はこのリンクwindows.hとwinsock2.hを見つけました。これは私にとってうまくいった代替手段を持っています:

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

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


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

私はいつもPostfix GUIDを使ってきました。数年前、同じファイル名の異なるヘッダーファイルがあり、ガードが含まれている非常に貧弱なコードベースに遭遇しました。問題のファイルは同じ名前のクラスを定義しています。名前空間のみが使用された場合。一部のプロジェクトはコンパイルしませんでした。一意のガードの使用は、ヘッダーとその内容を区別するためのソリューションの一部でした。

Visual StudioがインストールされたWindowsではguidgen.exeを使用し、Linuxではuuidgen -tを使用します。


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も含むモジュールではインクルードできません」

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

これが理にかなっている場合はお知らせください。


2

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

これらの行をヘッダーファイルの先頭に配置します。

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

そして底に

#endif

1
#pragma onceとinclude guardsは同じですよね?
akif 2009

それらはまったく同じではありません-ヘッダーガードはプリプロセッサレベルでのファイルの再包含を防止します。加えて、それらは明らかに#pragmaよりも少し移植性があります。
Timo Geusch

1
同じ目的で構築されていることを意味します:)
akif

2
#pragma onceは非標準のafaik
ntcong

2

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


シンボリックリンクまたはNTFSジャンクションもシステムを破壊します。
THOMI

1

#pragma onceMSコンパイラであっても不安定で、他の多くのコンパイラではサポートされていません。他の多くの人が述べたように、インクルードガードを使用する方法があります。まったく使用しない#pragma onceでください-それはあなたの人生をずっと簡単にします。


3
残念ながら、私はゼロ以上の誤ったインクルードガードを見てきました。タイプミスがガードが実際に機能しないことを意味するか、異なるディレクトリ内の同じ名前のファイルが同じトークンを使用するか、または使用されるトークンが二重で始まる場合アンダースコアまたはアンダースコアと大文字の組み合わせ(つまり、#pragma onceと同じように移植できません)。したがって、winsock.hを使用するものと同様に、本質的に移植性のないコードの場合、フレークだと言ったところまで、私は#pragmaにひどく悩まされていませんでした。まったくサポートされていない以外に、いつ失敗するのですか?
スティーブジェソップ

3
を使用する#pragma onceと、コンパイラはヘッダーファイルのノード名を一意のIDとして取得します。これは、ソースツリーにシンボリックリンクまたはNTFSジャンクションがある場合(考えられるよりも一般的)、または別のシステムインクルードディレクトリに同じ名前のファイルがある場合でも失敗する可能性があります(これは、 2つの異なるシステムインクルードパスにインストールされた同じライブラリのバージョン1およびバージョン2)。結論:私にとっては、コンパイラーが私のために行うのを信頼するのではなく、私はより多くの制御を持ち、時折のウェットウェアのミスに耐えることを好みます。
Thomi


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

0

私は実際にwinsock2.hを最初のインクルードとして定義しなければならない問題に遭遇しました、それは他のパッケージからのインクルードに他の問題があるようです。これがwindows.hだけでなく、すべてが含まれている同じ問題に遭遇する人に役立つことを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.