0

小さな 2D ゲーム用のフレームワークをセットアップしています。現在、いくつかのクラスしかありませんが、すぐにコンパイラの問題に陥っています。

関数のみでこのプログラムを実行したmainので、Allegro (グラフィックス ライブラリ) のライブラリ リンクが機能していることを確認できます。

ソリューション エクスプローラーの [ヘッダー ファイル] セクションにすべてのヘッダー ファイル (.h) を配置し、[ソース ファイル] セクションにすべてのソース (.cpp) を配置しました。この Allegro チュートリアルに従って、デフォルトから設定を変更しただけです: http://wiki.allegro.cc/index.php?title=Windows,_Visual_Studio_2010_and_Allegro_5。破壊的な方法で何かに影響を与えるべきではありませんでした。

いくつかのファイルがあるので、それぞれをリストします。サイズと冗長性を減らすために、いくつかのコードを省略します。コードを省略したり、逐語的でないことを行ったりする場合は、その旨を示すコメントをコードに入れます。(編集:実際にはコードをスキップしませんでした)

main.cpp

#include "common.h"

int main(int argc, char **argv)
{
   ALLEGRO_DISPLAY *display = NULL;
   World* world = new World(640, 480);

   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }

   display = al_create_display(640, 480);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      return -1;
   }

   al_clear_to_color(al_map_rgb(0,0,0));

   world->draw(display);

   al_flip_display();

   al_rest(10.0);

   al_destroy_display(display);

   return 0;
}

common.h

#if !defined(COMMON_INC)
#define COMMON_INC

#include "World.h"
#include "Pane.h"
#include <stdio.h>
#include <allegro5/allegro.h>

#endif

World.h

#if !defined(WORLD_INC)
#define WORLD_INC

#include "common.h"
#include "Pane.h"

class World{
public:
    World(int wp, int hp);
    void draw(ALLEGRO_DISPLAY* display);
    void update();


protected:

private:
    Pane* panel;
    int heightPix, widthPix;

};

#endif

World.cpp

#include "common.h"

World::World(int wp, int hp){
    widthPix = wp;
    heightPix = hp;
    panel = new Pane(this, 10, 10, 300, 400);
    return;
}

void World::draw(ALLEGRO_DISPLAY* display){
    panel->draw(display);
    return;
}

Pane.h

#if !defined(PANE_INC)
#define PANE_INC

#include "common.h"

class Pane{
public:
    Pane(World* w, int xv, int yv, int wi, int he);
    World* getWorld();
    int getZ();
    void draw(ALLEGRO_DISPLAY* display);
    ALLEGRO_BITMAP* getBackground();

protected:
    void setXY(int xv, int yv);
    void setWidthHeight(int wi, int he);
    void setZ(int zv);
    void setBackground(ALLEGRO_BITMAP* ba);

private:
    int z;
    int x, y; //pixels
    int width, height; //pixels
    World* world;
    ALLEGRO_BITMAP* background;
};

#endif

ペイン.cpp

#include "common.h"

Pane::Pane(World* w, int xv, int yv, int wi, int he){
    this->setWidthHeight(wi, he);
    this->setXY(xv, yv);
    this->world = w;
}

World* Pane::getWorld(){
    return world;
}

void Pane::setXY(int xv, int yv){
    x = xv;
    y = yv;
    return;
}

void Pane::setWidthHeight(int wi, int he){\
    width = wi;
    height = he;
    return;
}

void Pane::setZ(int zv){
    z = zv;
    return;
}

void Pane::draw(ALLEGRO_DISPLAY* display){
    if(background != NULL)
        al_draw_bitmap(background, x, y, 0);
    else{
        background = al_create_bitmap(width, height);

        al_set_target_bitmap(background);

        al_clear_to_color(al_map_rgb(255, 0, 255));

        al_set_target_bitmap(al_get_backbuffer(display));

        al_draw_bitmap(background, x, y, 0);
    }
    return;
}

コンパイラは、ビルド時に次のエラー レポートを生成します。

1>------ Build started: Project: MadScientist, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(8): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(11): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): warning C4183: 'getBackground': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(18): error C2061: syntax error : identifier 'ALLEGRO_BITMAP'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(10): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\main.cpp(22): error C2660: 'World::draw' : function does not take 1 arguments
1>  World.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(8): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(11): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): warning C4183: 'getBackground': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(18): error C2061: syntax error : identifier 'ALLEGRO_BITMAP'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(10): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(6): error C2661: 'Pane::Pane' : no overloaded function takes 5 arguments
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(10): error C2511: 'void World::draw(ALLEGRO_DISPLAY *)' : overloaded member function not found in 'World'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(7) : see declaration of 'World'
1>  Pane.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(8): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(11): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(12): warning C4183: 'getBackground': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(18): error C2061: syntax error : identifier 'ALLEGRO_BITMAP'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(24): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(10): error C2061: syntax error : identifier 'ALLEGRO_DISPLAY'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(3): error C2511: 'Pane::Pane(World *,int,int,int,int)' : overloaded member function not found in 'Pane'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(6) : see declaration of 'Pane'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(9): error C2556: 'World *Pane::getWorld(void)' : overloaded function differs only by return type from 'int *Pane::getWorld(void)'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9) : see declaration of 'Pane::getWorld'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(9): error C2371: 'Pane::getWorld' : redefinition; different basic types
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9) : see declaration of 'Pane::getWorld'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(10): error C2065: 'world' : undeclared identifier
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.cpp(30): error C2511: 'void Pane::draw(ALLEGRO_DISPLAY *)' : overloaded member function not found in 'Pane'
1>          c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(6) : see declaration of 'Pane'
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

あなたは私がしているすべての情報を持っています。すべてに目を通す手間を省くために、要約します。

  • ヘッダー インターフェイスとソース実装に分かれたクラスがあります。
  • common.h はすべてのファイルに含まれています。それ自体に、他のヘッダー ファイルのすべてのクラス定義が含まれます。
  • コンパイル時に、コンパイラは他のヘッダー ファイルで定義されたクラスをデータ型として認識しません。ご想像のとおり、エラーは連鎖的に発生します。
  • リアルタイム エラー チェッカーはエラーを登録しませPaneたとえば、 でデータ型として使用されているときに「World」という単語にカーソルを合わせると、型が完全に認識されます。リアルタイム エラー チェッカーは、コンパイラ時間の前に赤い下線がエラーに表示される機能です。
  • この Visual Studio 2012 Express は、前述の変更を除いて新しいものです。プロジェクトは、空の C++ プロジェクトとして作成されました。多くのヘッダーとソースが追加される前に、main関数は正しくコンパイルされました。

ご回答ありがとうございます。ご不明な点がございましたら、お尋ねください。私が Visual Studio で抱えている問題は、いつもイライラさせられます。

編集:

私の循環ヘッダー ロジックは、ヘッダー ガードによって保護されています。この冗長性は問題ではないと思います。

Allegro ライブラリへのインクルードを除いて、ヘッダー ファイルからすべてのインクルードを削除しようとしました。これはうまくいくように見えましたが、まだ奇妙な問題があります。含める行為がこれらのデータ型にエラーを引き起こす理由は、まだ謎です。新しいエラー ログは次のとおりです。

1>------ Build started: Project: MadScientist, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  World.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(6): error C2065: 'panel' : undeclared identifier
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(11): error C2065: 'panel' : undeclared identifier
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(11): error C2227: left of '->draw' must point to class/struct/union/generic type
1>          type is ''unknown-type''
1>  Pane.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

編集ラウンド 2:

コードを入れ替えて、common.h に stdio と Allegro のみが含まれるようにしました。すべてのヘッダー ファイルとソース ファイルには common.h が含まれており、その後、それらが個別に使用している任意のクラスのヘッダー ファイルが含まれています。Pane.cpp には、Pane.h と common.h が含まれています。World.h には、Pane.h と common.h が含まれます。

エラー ログの読み取り:

1>------ Build started: Project: MadScientist, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  World.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(9): error C2061: syntax error : identifier 'World'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(10): warning C4183: 'getWorld': missing return type; assumed to be a member function returning 'int'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\pane.h(25): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.cpp(7): error C2661: 'Pane::Pane' : no overloaded function takes 5 arguments
1>  Pane.cpp
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C2143: syntax error : missing ';' before '*'
1>c:\users\ethoma\documents\visual studio 2012\projects\madscientist\madscientist\world.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

これが今のインクルードオーダーの見方です:

  1. メイン インクルード 共通
  2. common は COMMON_INC を定義します
  3. 共通には stdio と allegro が含まれます
  4. main インクルード World.h
  5. World は WORLD_INC を定義します
  6. ワールドにはブロックされたコモンが含まれます。しかし、コモンはすでに含まれているので、これは問題ないはずです
  7. ワールド インクルード ペイン
  8. ペインは PANE_INC を定義します
  9. ペインには、ブロックされている共通が含まれています。しかし、common は既に含まれているので、これで問題ないはずです。
  10. ペインには World が含まれます。main には既に World が含まれているため、これはブロックされます。World は既に含まれているので、これで問題ないはずです。ファイルを使用するファイルごとに 1 回、何度もファイルを含める必要がある場合、なぜコンパイラ ガードがあるのでしょうか。

編集ラウンド 3: ここでの回答とコメントから多くのことを学びました。ウィキペディアによると、「循環依存関係は、ある種のコールバック機能を実装する必要がある経験の浅いプログラマーによって導入されることが多い」ことが判明しています。Pane が World を使用し、World が Pane を使用するという単なる事実は、設計上の欠陥です。Java では、これで問題ありませんでした。とても簡単でした。オブジェクトを「所有」しているエンティティにオブジェクトのアクションを通知するには、これが最善の方法であると考えました。

これは悪い設計スキームであることがわかりました。オブジェクトは、その「所有者」に依存するべきではありません。代わりに、オブザーバー システムを実装する必要があります。このシステムでは、Pane が状態を更新したことを World に伝えることができます。

ウィキペディアを読んで疑問が解消されたので、この質問は終了したと考えています。学習プログラマーのために我慢してくれた貢献者に感謝します。

4

2 に答える 2

6

ヘッダー ファイルを正しくリンクできない可能性があります。循環形式でヘッダーを含めました。ヘッダー ファイルにはが含まれcommon.hていますが、やcommon.hなどの他のヘッダーも含まれています。World.hPane.h

これは、どのコンパイラでもコンパイルできません。低レベルのヘッダーから高レベルのヘッダーまでヘッダーの階層を作成し、高レベルのヘッダーには低レベルのヘッダーのみが含まれるようにする必要があります。そうすれば、円形のインクルージョンがないことを確認できます。

とにかく、なぜ と がcommon.h含まれWorld.hているのPane.hですか? これは明らかなエラーのように見えます。common.h低レベルのヘッダーを意図しています。World.hそれを含めてみましょう。ただし、にPane.h含めないでWorld.hください。Pane.hcommon.h

この場合、ヘッダー ガードは何も解決しないことに注意してください。インクルージョンサイクルが無限にならないようにするだけです。それらはサイクルを壊しますが、宣言間の循環依存関係が存在する場合、それらを解決するのには役立ちません。

処理時にあなたのケースで何が起こるか見てくださいmain.cpp

  1. main.cpp含むcommon.h
  2. common.h定義するCOMMON_INC
  3. common.h含むWorld.h
  4. World.h定義するWORLD_INC
  5. World.h含まれていcommon.hます。ステップ 2 で定義されているため、インクルード ガードによって全体がスキップされます。common.hCOMMON_INC
  6. World.h含むPane.h
  7. Pane.h定義するPANE_INC
  8. Pane.h含まれていcommon.hます。ステップ 2 で定義されているため、インクルード ガードによって全体がスキップされます。common.hCOMMON_INC
  9. Pane.hタイプ と呼ばれWorldます。型Worldはまだ定義されていないため、不明World.hです。エラー!
于 2012-12-08T03:07:36.727 に答える
1

次の変更を加えれば、循環インクルードでもすべてがコンパイルされると思います

  1. common.hヘッダーの順序を並べ替える必要があります。

    #include <allegro5/allegro.h>
    #include "World.h"
    #include "Pane.h"
    #include <stdio.h>
    
  2. pane.hの の後に#include common.h、 の前方宣言を追加します。class World

    #include "common.h"
    class World;
    class Pane{
     .....
    

これにより、エラーが消えるか、少なくとも大幅に減少すると思います。私の答えは、編集ではなく、あなたが作成した元のコードに基づいています。

于 2012-12-08T03:35:43.500 に答える