0

次のようにヘッダーファイルに構造を作成しました。

typedef struct
{
    GLfloat lgtR, lgtG, lgtB, lgtA;
    GLfloat x, y, z;
    bool islight;
    GLfloat width, height, depth;
    GLenum lightn;
    particle prt;
    int maxprt;
} emitter;

これは問題なく動作します。

ただし、その特定のヘッダーファイルでは、すべての関数で使用でき、メインのソースファイルの一部ではないグローバルエミッターを宣言したいと思います。

// header.h global declaration

emmiter currentEmit;

GLvoid glSetEmitter(emitter emitter)
{
    currentEmit = emitter;
}

ただし、これを試してみると、「エラーC2228:'.variable'の左側にclass/ struct / unionが必要であるため、ここで構造体がまったく宣言されていないことを前提としています。

その構造をヘッダーファイル内でグローバルに宣言する方法はありますか?もしそうなら、それが他の.cppファイルの一部にならないようにする方法もありますか?

4

2 に答える 2

7

emitterと同じではありませんemmiter

また、これは C++struct {};であるため、直接記述するだけなので、typedef.

ヘッダー全体が間違っており、複数の翻訳単位に含まれていると複数の定義が得られます。

// header.h global declaration
extern emitter currentEmit;   // <-- note extern

inline GLvoid glSetEmitter(emitter emitter)  // <-- note inline
{
    currentEmit = emitter;
}

currentEmitヘッダーではなく、単一の実装ファイルで定義する必要があります。inline関数は、すべての TU で定義されないようにする必要があります。

最後に: パラメータを const 参照で渡します。

inline GLvoid glSetEmitter(const emitter& emitter)  // <-- note inline
{
    currentEmit = emitter;
}

そうしないと、不要なコピーが作成されます。

于 2012-07-11T16:15:39.960 に答える
1
typedef struct
{
    GLfloat lgtR, lgtG, lgtB, lgtA;
    GLfloat x, y, z;
    bool islight;
    GLfloat width, height, depth;
    GLenum lightn;
    particle prt;
    int maxprt;
} emitter;

あるべき

struct Emitter
{
    GLfloat lgtR, lgtG, lgtB, lgtA;
    GLfloat x, y, z;
    bool islight;
    GLfloat width, height, depth;
    GLenum lightn;
    particle prt;
    int maxprt;
};

ヘッダーファイル内でその構造をグローバルに宣言する方法はありますか?

はい、各コンパイル単位で変数が作成されないようにするには、主に 2 つの方法があります。

まず、マイヤーズ シングルトンがあります。

namespace g {
    inline Emitter& emitter()
    {
        static Emitter theEmitter;
        return theEmitter;
    }
}

void foo() { g::emitter().x = 666; }

次に、テンプレート化のトリックがあります。

namespace detail {
    template< class Dummy >
    struct EmitterVariable
    {
        static Emitter v;
    };

    template< class Dummy >
    Emitter EmitterVariable<Dummy>::v = {};
}

namespace g {
    static Emitter& emitter = EmitterVariable<void>::v;
}

void foo{ g::emitter.x = 666; }

もしそうなら、それが他の .cpp ファイルの一部にならないようにする方法もありますか?

はい、上記のソリューションはどちらもそれを行います。

ただし、最後のものは各コンパイル単位に参照を挿入します。これは実際にはポインターのサイズになります。

とはいえ、グローバル変数は非常に厄介なデータ フローを与える傾向があります。コードのどの部分がそこに何かを置いているのかわかりません。適切に初期化されているかどうか、またはいつ初期化されているかはわかりません。ここでデータを変更すると、他のどの部分が影響を受けるかわかりません。またはいつ。等々。したがって、それは絶対に良い考えではありません。グローバル定数は OK ですが、グローバル変数は No と言ってください。

于 2012-07-11T17:23:08.380 に答える