0

私はまだ C++ と OOP の設計の基礎を学ぼうとしている初心者のプログラマーです。私が独学で取り組んでいるプロジェクトは、複数のクラス、ファイル、ステートなどを持つ C++ ゲームです。しかし、コンパイルするオブジェクトをどこに作成するかという単純な問題から、さまざまなファイル編成の問題に直面し続けています。リンカエラーの破壊。

これは、私が取得しているエラーの例です。

1>SMGA.obj : error LNK2005: "class Engine smgaEngine" (?smgaEngine@@3VEngine@@A) already defined in Engine.obj
1>SplashScreenState.obj : error LNK2005: "class Engine smgaEngine" (?smgaEngine@@3VEngine@@A) already defined in Engine.obj
1>StateManager.obj : error LNK2005: "class StateManager gameStateManager" (?gameStateManager@@3VStateManager@@A) already defined in Engine.obj
1>MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library

私はオンラインで見回しましたが、不適切なインクルード ガードや .h ファイルの代わりに .cpp ファイルを含めることに関連する多くの ~similar~ 問題を見てきました。しかし、私は自分のコードでそれを行っていないので、途方に暮れています。

エラーは、Engine クラスの smgaEngine オブジェクト (および StateManager クラスの gameStateManager オブジェクト) を 2 回作成しようとしていることを示していると推測していますが、その理由はわかりません...

これら 2 つのオブジェクト (smgaEngine と gameStateManager) で際立っているのは、クラス宣言の直後に対応するクラスの .h ファイルで宣言したことです。これが問題でしょうか?- それらはまだインクルード ガード内にあり、コード内のどこに配置すればよいかよくわかりませんでした... このずさんなコーディングはリンカ エラーの原因になるのでしょうか?

これが疑わしいクラスの1つです...

#ifndef ENGINE_H
#define ENGINE_H

#include <SDL.h>
#include "Timer.h"

class Engine
{
private:
    static const int screenWidth = 480;
    static const int screenHeight = 270;
    static const int screenBPP = 24;

    bool running;
    SDL_Surface *mainScreen;
    SDL_Event eventHolder;
    Timer fpsTimer;

public:
    Engine();
    ~Engine();

    void init();
    void handleEvents();
    void handleLogic();
    void handleRender();
    void cleanUp();

    SDL_Event *getEvent();

    SDL_Surface *getMainScreen();

    bool isRunning();
    void setRunning(bool tempRunning);
} smgaEngine;

#endif 

もう 1 つは次のとおりです。

#ifndef STATEMANAGER_H
#define STATEMANAGER_H

#include "SplashScreenState.h"
#include <vector>

class GameState;

class StateManager
{
private:
    std::vector<GameState*> stateStack;

    SplashScreenState *splashState;

public:
    StateManager();
    ~StateManager();

    void init();

    void changeState( GameState *tempNextState );
    void addState( GameState *tempNextState );
    void removeState();

    //returns the back() element of the stateStack vector..
    GameState* getTopState();

    void handleEvents();
    void handleLogic();
    void handleRender();
} gameStateManager;

#endif

私は C++ と OOP を学ぶために最善を尽くしてきましたが、本当に苦労しています。カプセル化されたクラスできれいなコードを作成しようとするたびに、混乱する混乱に陥ってしまうようです。高度なクラス結合を防止しようとしていますが、多くの場合、リンカ エラーが発生するか、クラス間で通信できなくなります...これらのエラーの原因となっているヘッダー ファイル内のクラス インスタンス オブジェクトの作成ですか?それとも何か他のものですか?それがリンカー エラーの原因である場合、これらのオブジェクトはどこで作成する必要がありますか?

4

1 に答える 1

6

ヘッダー ファイルで2 つのグローバル変数を定義smgaEnginegameStateManager、それらのヘッダー ファイルを 2 つ (またはそれ以上) のソース ファイルに含めました。したがって、複数の定義エラーが発生します。インクルード ガードは、ヘッダー ファイルが異なるソース ファイルに 2 回インクルードされるのを止めません (どうすればよいでしょうか?) 。同じソース ファイルにヘッダー ファイルが 2 回インクルードされるのを防ぎます。

あなたは正しい答えにかなり近づいています (少なくとも問題をよく理解しています)。正しいやり方はこれ

// header file Engine.h
class Engine
{
};

extern Engine smgaEngine;

// in one source file (say Engine.cpp)
Engine smgaEngine;

あなたが今持っているのは、ヘッダーファイルの宣言externです(それを宣言にします)が、ソースファイルの定義です。(一貫性がある限り) 好きなだけ宣言を行うことができますが、定義は 1 つだけにする必要があります。したがって、グローバル変数の場合、宣言をヘッダー ファイルに入れ、定義をソース ファイルの 1 つに入れます。

于 2012-09-08T06:57:31.123 に答える