4

私は最近、複数のファイルインクルードエラーに苦しんでいます。私はスペースアーケードゲームに取り組んでおり、クラス/オブジェクトを異なる.cppファイルに分割し、すべてが正常に機能することを確認するために、次のヘッダーファイルを作成しました。

#ifndef SPACEGAME_H_INCLUDED
#define SPACEGAME_H_INCLUDED
//Some Main constants
#define PI 3.14159265


//Standard includes
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;

//SDL headers
#include "SDL.h"
#include "SDL_opengl.h"
#include "SDL_mixer.h"
#include "SDL_image.h"

//Classes and project files
#include "Player.cpp"
#include "planet.cpp"
#include "Destructable.cpp"
#include "PowerUp.cpp"
#include "PowerUp_Speed.cpp"

#endif // SPACEGAME_H_INCLUDED

そして、すべてのファイルの上部に、すべての.cppファイルと標準インクルードを保持するこのヘッダーファイル(のみ)をインクルードしました。

ただし、「 Shipクラスの再定義」タイプのエラーが発生したPlayer/Shipクラスがあります。最終的に、クラス定義ファイルにプリプロセッサの#ifndefコマンドと#defineコマンドを含めることで回避策を見つけました。

#ifndef PLAYER_H
#define PLAYER_H
/** Player class that controls the flying object used for the space game */
#include "SpaceGame.h"


struct Bullet
{
  float x, y;
  float velX, velY;
  bool isAlive;
};

class Ship
{
    Ship(float sX,float sY, int w, int h, float velocity, int cw, int ch)
    {
        up = false; down = false; left = false; right = false;
        angle = 0;
....
#endif

この回避策により、「class / struct redefinition」エラーが失われましたが、Shipクラスを必要とするクラスファイルPowerUp_Speedに奇妙なエラーが発生しました。

#include "SpaceGame.h"

class PowerUp_Speed : public PowerUp
{

    public:
        PowerUp_Speed()
        {
            texture = loadTexture("sprites/Planet1.png");
        }

        void boostPlayer(Ship &ship)
        {
            ship.vel += 0.2f;
        }
};

次のエラーが発生しました:'不完全な型の無効な使用'structShip' 'および' structship' 'の前方宣言

これらのエラーの原因は、複数のファイルインクルードエラーに関する私の問題にあると思います。エラーの量を減らすために行ったすべての手順を説明しましたが、これまでのところ、Googleで見つけたすべての投稿は役に立たなかったので、その原因を見つけるのを手伝ってくれる人がいるかどうか丁寧に尋ねています。問題と修正。

4

1 に答える 1

9

通常、cppファイルは含めません。
ヘッダーファイルのみをインクルードする必要があります!

cppファイルを含めると、単一定義規則(ODR)に違反することになります。
通常、ヘッダーファイル(.h)はクラス/構造などを定義し、ソース(.cpp)ファイルはメンバー関数などを定義します。ODR
に従って、同じcppを含む各変数/関数などの定義のみを持つことができます。複数のファイルにファイルがあると、複数の定義が作成されるため、ODRが壊れます。

これについてはどうすればいいですか?

オブジェクトを作成したり、メンバー関数などを呼び出したりできるようにするには、オブジェクトなどを作成する必要があるソースファイルにそのクラスを定義するヘッダーファイルを含めるだけです。ソースファイルをどこにも含める必要はありません。 。

前方宣言はどうですか?

ヘッダーファイルをインクルードする代わりに、前方宣言クラスまたは構造を使用することが常に推奨されます。これには、次のような大きな利点があります。

  • コンパイル時間の短縮
  • グローバル名前空間の汚染はありません。
  • プリプロセッサ名の潜在的な衝突はありません。
  • バイナリサイズの増加なし(常にではない場合もあります)

ただし、型を前方宣言すると、コンパイラはその型を不完全な型と見なすため、限られた操作しか実行できません。したがって、宣言を常に転送するようにする必要がありますが、常にそうすることはできません

于 2012-06-17T11:51:40.017 に答える