🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

1回答

937閲覧

ヘッダーが衝突する場合のインクルードエラーの解決方法が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

1クリップ

投稿2021/02/25 12:44

下記のGame_Scene クラスのインクルードですがなぜstage.hppをインクルードするとstageクラス内の#define つまりEntry.hpp関係が読み込まれないのでしょうか?ヘッダーファイルが衝突していると思いEntry.hppをコメントアウトしてStage.hppをインクルードしたり前方宣言やら色々試しましたがわかりません。どうすればいいのでしょうか?

hpp

1#ifndef ___STAGE_HPP_ 2#define ___STAGE_HPP_ 3 4#include "Entry.hpp" 5 6/*#################################################### 7* エディットするステージを描画 8* 9* 説明 10* 11* 12######################################################*/ 13 14class Stage 15{ 16public: 17 Stage(); //コンストラクタ 18 ~Stage(); //デストラクタ 19 20 void Update(); //計算 21 void Draw(); //描画 22 23private: 24 25 26 byte mGame_Stage[ STAGE_GRID_Y ][ STAGE_GRID_X ]; //ステージ 27}; 28 29 30#endif

hpp

1#ifndef ___GAME_SCENE_HPP_ 2#define ___GAME_SCENE_HPP_ 3 4#include "Scene_base.hpp" 5//#include "Entry.hpp" 6#include "Stage.hpp" 7 8 9enum class Scene_Type; 10class Stage; 11/*#################################################### 12* メインゲーム シーン 13* 14* 説明 15* メインのゲーム画面 16######################################################*/ 17class Game_Scene : public Scene_base 18{ 19public: 20 Game_Scene(Scene_Type t,Entry* e); //コンストラクタ 21 ~Game_Scene(); //デストラクタ 22 23 void Update(); //更新 24 void Draw(); //描画 25 26private: 27 28 29 30 std::shared_ptr<Stage> stage; 31 32 Entry* Owner; //Entry クラス 33 34}; 35 36#endif 37

hpp

1#ifndef ___ENTRY_HPP_ 2#define ___ENTRY_HPP_ 3 4 5 6#include "Game_Scene.hpp" 7#include "Input.hpp" 8#include <iostream> 9class Game_Scene; 10 11 12 13#define CELL ((int)48) //セル 14 15#define byte unsigned char //バイト 16 17//画面サイズ 18#define SCREEN_WIDTH ((int)16 * 70) 19#define SCREEN_HEIGHT ((int)9 * 70) 20 21//ステージ 22#define STAGE_WIDTH ((int)100 * CELL) 23#define STAGE_HEIGHT ((int)100 * CELL) 24 25//ステージのセル数 26#define STAGE_GRID_X ((int)(STAGE_WIDTH / CELL)) 27#define STAGE_GRID_Y ((int)(STAGE_HEIGHT / CELL)) 28 29//方向 30#define VECTOR_UP glm::ivec2(0,-1) 31#define VECTOR_DOWN glm::ivec2(0,1) 32#define VECTOR_LEFT glm::ivec2(-1,0) 33#define VECTOR_RIGHT glm::ivec2(1,0) 34 35#define PI ((float)3.14159265359) //PI 36 37 38 39// シーンの種類 40enum class Scene_Type 41{ 42 Title, //タイトル 43 Game, //メインゲーム 44 GameOver, //ゲームオーバー 45 46 47 Menu, //メニュー 48 Pause, //一時停止 49}; 50 51 52 53/*#################################################### 54* シーン推移 55* 56* 説明 57* シーンの推移を行う 58######################################################*/ 59class Entry 60{ 61public: 62 63 Entry(); //コンストラクタ 64 ~Entry(); //デストラクタ 65 66 void Update(); //計算 67 void Draw(); //描画 68 int GetRand(int start, int end); //乱数を取得 69 70 int LoadSprite(const char* FileName); //スプライトをロード 71 72 73 std::shared_ptr<Input> InputKey; 74 75private: 76 77 std::shared_ptr<Game_Scene> game; 78 79 Scene_Type type; 80 81}; 82 83 84#endif 85 86

hpp

1#ifndef ___SCENE_BASE_HPP_ 2#define ___SCENE_BASE_HPP_ 3 4#include <iostream> 5#include <vector> 6 7class Entry; 8enum class Scene_Type; 9 10/*#################################################### 11* シーンの基底クラス 12* 13* 説明 14* 全てのシーンクラスはこのクラスを継承する。 15######################################################*/ 16class Scene_base 17{ 18public: 19 Scene_base(Scene_Type t,Entry* e); //コンストラクタ 20 ~Scene_base(); //デストラクタ 21 22 virtual void Update() = 0; //更新 23 virtual void Draw() = 0; //描画 24 25 Scene_Type getSceneType(); //シーンタイプを取得 26protected: 27 28 Scene_Type Type; //シーンタイプ 29 Entry* Owner; //Entry クラス 30 31}; 32 33 34#endif 35

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

txty

2021/02/25 13:23

忘却の彼方だし、素人の考えで笑われるかもしれませんけどヘッダファイルに #ifndef  #define#endifするけどそこに書くのはクラスで  cpp側で#includeすればいいんじゃないの ポインタの扱いがよくわかんなくて避けてるけど誰か助けて。
退会済みユーザー

退会済みユーザー

2021/02/25 13:26

どういう意味でしょうか?
txty

2021/02/25 13:32 編集

.cpp側でインクルードすればよくてヘッダ側でインクルードしてるからおかしいのかなと思った。過去に書いた資料みてみてそうかなと思った。
退会済みユーザー

退会済みユーザー

2021/02/25 13:34

ソースファイル側でインクルードするのは正しいのでしょうか?
txty

2021/02/25 13:41

私はそうしてるけどそんなんで問題解消するか知らない
txty

2021/03/04 03:34 編集

書き込みがなくなったので、どうなったのか気にしてます。 また、今回のコメント欄に貼ったコメントは 参考にしないでください。
guest

回答1

0

ベストアンサー

Entry.hpp ⇨ Game_Schene.hpp ⇨ Stage.hpp ⇨ Entry.hpp の循環インクルードになっています。Stage.hpp より先に Entry.hpp が読み込まれると、STAGE_GRID_X が定義される前に Stage.hpp がインクルードされるためコンパイルできなくなります。

質問者さまが過去に4回ぐらい遭遇している循環インクルードの問題ですが、今回は Stage.hpp 内でクラスの前方宣言することでは解消できませんね。

  • Entry.hpp 内で Game_Scene.hpp をインクルードせず、前方宣言で済ませる
  • Entry.hpp 内の定数定義だけを別ヘッダに追い出して、Stage.hpp では Entry.hpp の代わりにそれをインクルードする

のどちらかでいいと思います。


毎回 Entry.hpp が問題を起こしていますが、「Entry.hpp からは他のヘッダをインクルードするのは避ける。前方宣言で済ませる」と「ヘッダからEntry.hppをインクルードするのを避ける。可能なら前方宣言で済ませる」でだいたい解消すると思います。

追記: Entry.hpp の設計について:
Entry.hpp には「いろいろなクラスで使われる定数・関数(Entry::GetRand()Entry::LoadSprite())」と「ゲーム全体を制御する(?)クラス class Entry」が混在しています。これらの役割を別ヘッダに分けるのが循環参照のない理想的な設計です。かといって Entry::GetRand()Entry::LoadSprite()Entry クラスに存在する理由もあるでしょうから、一部を抽象クラスにしてしまうのが良いと思います。おおまかな例:

Entry.hpp (いろいろなクラスから使うのはこのヘッダ。.cpp は不要。)

c++

1 2#define CELL ((int)48) 3... 4 5class Entry { 6 public: 7 virtual ~Entry() {} 8 virtual int GetRand(int start, int end) = 0; 9 virtual int LoadSprite(const char* FileName) = 0; 10};

EntryImpl.hpp (ゲーム全体の制御はこれ)

c++

1#include "Entry.hpp" 2 3class EntryImpl : public Entry { 4 EntryImpl(); 5 ~EntryImpl() override; 6 7 void Update(); 8 void Draw(); 9 10 int GetRand(int start, int end) override; 11 int LoadSprite(const char* FileName) overide; 12 13 std::shared_ptr<Input> InputKey; 14 15private: 16 std::shared_ptr<Game_Scene> game; 17 Scene_Type type; 18};

投稿2021/02/25 15:56

編集2021/02/26 02:34
int32_t

総合スコア21679

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/02/26 00:52

Entry.hppを読み込ませるて定数を使うというやり方が既に危険で良くないのでしょうか?
退会済みユーザー

退会済みユーザー

2021/02/26 01:00

またソースファイルで.hppをインクルードするという手段は正しいのでしょうか?
int32_t

2021/02/26 01:20

> Entry.hppを読み込ませるて定数を使うというやり方が既に危険で良くないのでしょうか? Entry.hppがトラブルを生みやすい設計ですが、前方宣言などで回避できるのなら大した問題ではないです。 どういう設計をしたらいいのか、回答に追記しておきました。 > またソースファイルで.hppをインクルードするという手段は正しいのでしょうか? ごく普通に行われることです。正しくコンパイルできれば何も問題はありません。
退会済みユーザー

退会済みユーザー

2021/02/26 01:22

なるほど。 > Entry.hpp 内で Game_Scene.hpp をインクルードせず、前方宣言で済ませる とありますがソースファイル側で.Game_Scene.hppをインクルードする必要があるのですが大丈夫なのでしょうか?
int32_t

2021/02/26 01:27

> ソースファイル側で.Game_Scene.hppをインクルードする必要があるのですが 既に書いたように、問題ありません。何を心配しているのかわかりませんが、必要なときに必要なヘッダをインクルードするのはごく当然のことです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問