5
game.h needs:
- packet.h
- socket.h

server.h needs:
- socket.h

socket.h needs:
- game.h

socket.h には game.h が既に含まれているため、socket.h を game.h に含めようとすると問題が発生します。このような問題を解決するにはどうすればよいですか?

4

6 に答える 6

17

通常の方法では、ヘッダー ファイルで #ifdef と #define を使用します。

game.h 内:

#ifndef GAME_H
#define GAME_H

.. rest of your header file here

#endif

このように、コンテンツは複数回読み取られますが、定義は 1 回だけです。

編集:コメントごとに識別子の先頭と末尾にあるアンダースコアを削除しました。

于 2008-12-21T13:02:38.120 に答える
9

鍵は前方宣言です。(またはその逆) でgame.h必要なものを取得し、さらに別のヘッダーで前方宣言します。例として、次のことを考慮してください。socket.hgame_forwards.h

// game_fwd.h

#ifndef GAME_FWD_H
#define GAME_FWD_H

class game;

#endif // ndef GAME_FWD_H

// game.h

#ifndef GAME_H
#define GAME_H

#include "socket.h"

class game {
    socket* m_sck;
};

#endif // ndef GAME_H

// socket.h

#ifndef SOCKET_H
#define SOCKET_H

#include "game_fwd.h"

class socket {
    game* m_game;
};

#endif // ndef SOCKET_H

明らかに、これが機能するためには、インターフェースと実装を分離することが重要です。

于 2008-12-21T13:05:31.483 に答える
8

テクニック(フォワード定義とread-onceヘッダー)に加えて、ソケットヘッダーがゲームヘッダーから何かを必要とする理由を解明し、単一の依存関係の順序でシステムをモジュールにパッケージ化する必要があります。ソケットクラスがどのゲームに使用されているかを知る必要がある理由はないはずです。

于 2008-12-21T15:50:28.107 に答える
3

完全を期すために、別の代替手段は次のとおりです。

#pragma once 

ファイルの上部にあります。

これには、ファイルが繰り返し開かれず、コンパイル時間が節約されるという利点があります。

標準ではないという欠点があるため、すべてのコンパイラがサポートしているわけではありません。Visual C++ で確実に動作します。

于 2008-12-21T16:02:07.243 に答える
1

私が考えることができるエレガントな方法はありません-あなたの最善の策は、実際に使用される関数を前方定義することです. したがって、game.h が socket.h の connect() 関数のみを使用する場合は、次の行を game.h に追加します。

void connect();

そして、socket.h インポートを削除します。もちろん、connect() の署名が変更された場合は、前方定義も更新することを忘れないでください。そのため、このソリューションは理想とはほど遠いものです。可能であれば、設計を変更して循環依存を回避してください。

game.h が socket.h 内のクラスについて知る必要があるだけの場合は、次のように前方定義します。

class Socket;

インライン関数とメンバー オブジェクトに関しては、いくつかの注意事項があります。 The C++ FAQ Liteを参照してください。

于 2008-12-21T13:17:57.480 に答える
0

@lassevk、「ヘッダーファイルは数回開かれますが、プリプロセッサは最初の読み取り中に #ifndef と #endif の間のファイルの内容のみを読み取ります。その後、プリプロセッサは bewteen を無視します。 _GAME_H が定義されているため、PP マクロ。

于 2008-12-21T13:08:24.253 に答える