ヘッダーファイルを2回インクルードしないようにするにはどうすればよいですか?問題は、in 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'
この問題は、<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 もご覧ください。
他の人が示唆したように、問題は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.h
の代わりにwinsock.h
を使用します(ほとんどの場合)。これにより、おそらくコンパイル時間が長くなりますが、エラー/警告は解決されます。
ああ-Windowsのさ...ここではインクルードの順序が重要です。 windows.hの前にwinsock2.hを含める必要があります。 windows.hはおそらくプリコンパイル済みヘッダー(stdafx.h)からインクルードされるため、そこからwinsock2.hをインクルードする必要があります。
#include <winsock2.h>
#include <windows.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.hが含まれていると思われるサードパーティのパッケージをプルしようとしたときに、この問題に遭遇しました。プロジェクトレベルで_WINSOCKAPI_
を定義することは、スープを歩いて問題のあるインクルードを修正するよりもはるかに簡単です(保守が容易であることは言うまでもありません)。
VS 2015では、以下が機能します。
#define _WINSOCKAPI_
以下はできません:
#define WIN32_LEAN_AND_MEAN
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を使用します。
再帰的なインクルードを確認し、いくつかの#include "windows.h"
と "#include" Winsock.h "and write a
#include" Winsock2.h ". in this files, i added
#includeを含む(再帰的に)ヘッダーファイルを見つけました。最初のインクルードとして「Winsock2.h」 `。
忍耐の問題として、最初に#include "Winsock2.h"
を、次に#include "windows.h"
を順番に確認してこの順序を確立します
私はこのリンクを見つけました windows.h and winsock2.h これは私にとってうまくいった代替手段を持っています:
#define _WINSOCKAPI_ // stops windows.h including winsock.h
#include <windows.h>
#include <winsock2.h>
問題が発生した場所を見つけるのに苦労していましたが、その#defineを追加することで、それを理解することなく構築することができました。
私は同じ問題に遭遇しました、そして、ここに私がこれまで発見したものがあります:
この出力フラグメントから-
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も含むモジュールによって含めることはできません」
コードを変更せずに問題を修正しようとしています。
これが理にかなっているかどうか教えてください。
#pragma once
は、ファイル名のフルパスに基づいています。したがって、MyClass.hまたはWinsock2.hの2つの同一のコピーが異なるディレクトリにある可能性があります。
ヘッダーガードを使用する必要があります。
これらの行をヘッダーファイルの先頭に配置します
#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H
そして下部に
#endif
#include guards は、これを行う標準的な方法です。 #pragma once はサポートされていません。つまり、すべてのコンパイラがサポートしているわけではありません。
私のプロジェクト(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")
#pragma once
は、MSコンパイラーであってもフレークであり、他の多くのコンパイラーではサポートされていません。他の多くの人が言及しているように、インクルードガードを使用する方法があります。 #pragma once
を使用しないでください-生活がずっと楽になります。
実際には、最初のインクルードとしてwinsock2.hを定義する必要がある問題に遭遇しました。他のパッケージのインクルードには他の問題があるようです。これがwindows.hだけでなくすべてに含まれる同じ問題に遭遇した人に役立つことを願っています。