0

これらのファイルを作成しようとしていますが、複数の定義エラーが発生します。

main.cpp:

#include "SDL/SDL.h"
#include "Core.h"
#include "GameStates.h"
#include "globals.h"

int main(int argc, char** args) 
{
if(core.Initilization(640, 480, 32, SDL_SWSURFACE) == -1)
{
    SDL_Quit();
}

while(core.desiredstate != core.quit)
{
    ::currentstate->EventHandling();
    ::currentstate->Logic();
    core.ChangeState();
    ::currentstate->Render();
    ::currentstate->Update();
}

SDL_FreeSurface(core.screen);
SDL_Quit();

}

Core.cpp:

#include "Core.h"
#include "GameStates.h"
#include "SDL/SDL.h"
#include "Intro.h"
#include "globals.h"
#include <string>

/* Starts SDL subsystems and sets screen attributes */
bool Core::Initilization(int SCREEN_WIDTH, int SCREEN_HEIGHT, int SCREEN_BPP, int FLAGS) 
{
    //starts SDL subsystems, returns false upon error
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
    return false;
}

//The screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, FLAGS);
//Returns false if there was an error
if(screen == NULL)
{
    return false;
}

SDL_WM_SetCaption("Game", NULL);

return true;
}

/* Loads an image and optimizes it */
SDL_Surface* Core::Load(std::string filename)
{
//original loaded image
SDL_Surface* original = SDL_LoadBMP(filename.c_str());
SDL_Surface* optimized = NULL;

if(original != NULL)
{
    //Sets optimized to optimized version of original
    optimized = SDL_DisplayFormat(original);

    SDL_FreeSurface(original);
}

return optimized;
} 

/* Blits surfaces */
void Core::ApplySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination) 
{
//holds the x y coordinates
SDL_Rect location;
location.x = x;
location.y = y;

if(destination != NULL) 
{
    SDL_BlitSurface(source, NULL, destination, &location);
}
}

/* Sets desiredstate to be used in ChangeState(); */
void Core::SetState(int newstate) 
{
if(desiredstate != state_null && desiredstate != quit)
{
    desiredstate = newstate;
}
}

/* Changes the game state */
void Core::ChangeState()
{
    if(desiredstate != state_null && desiredstate != quit)
    {
        //frees old state memory
    delete ::currentstate;

    switch(desiredstate)
    {
        case intro:
            //allocates new state memory
            ::currentstate = new Intro();
        break;
    }

    stateID = desiredstate;
    desiredstate = state_null;
}
}

GameStates.h:

#ifndef GAMESTATES_H
#define GAMESTATES_H

class GameStates 
{
public:
    virtual void EventHandling() = 0;
    virtual void Logic() = 0;
    virtual void Render() = 0;
    virtual void Update() = 0;
};

#endif

Intro.h:

#ifndef INTRO_H
#define INTRO_H
#include "SDL/SDL.h"
#include "GameStates.h"

class Intro : public GameStates
{
    private:
    SDL_Surface* test;
public:
    Intro();
    void EventHandling();
    void Logic();
    void Render();
    void Update();
    ~Intro();
} intro;

#endif

Intro.cpp:

#include "Intro.h"
#include "GameStates.h"
#include "Core.h"
#include "SDL/SDL.h"

Intro::Intro()
{
test = core.Load("test.bmp");
}

void Intro::EventHandling()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
    switch(event.type)
    {
        case SDL_QUIT:
            core.SetState(core.quit);
        break;
    }
}
}

void Intro::Logic()
{
//to be coded when the program actually builds...
}
void Intro::Render()
{
core.ApplySurface(30, 30, test, core.screen);
}

void Intro::Update()
{
SDL_Flip(core.screen);
}

Intro::~Intro()
{
SDL_FreeSurface(test);
}

globals.h:

#include "GameStates.h"
#include "SDL/SDL.h"

GameStates* currentstate = NULL;

インデントがオフの場合は申し訳ありません。コードブロックが少し混乱しているように見えるようにするには、4つのスペースを入れる必要があります。

エラーメッセージは次のとおりです。

/tmp/ccWxKsO5.o:(.bss+0x0): multiple definition of `core'
/tmp/cc13Eqmt.o:(.bss+0x0): first defined here
/tmp/ccWxKsO5.o:(.bss+0x20): multiple definition of `currentstate'
/tmp/cc13Eqmt.o:(.bss+0x10): first defined here
/tmp/ccJXxewI.o:(.bss+0x0): multiple definition of `intro'
/tmp/ccWxKsO5.o:(.bss+0x10): first defined here
/tmp/ccJXxewI.o:(.bss+0x10): multiple definition of `core'
/tmp/cc13Eqmt.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

Makefile:

OBJS = main.o Intro.o Core.o
CC = g++
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LIBS = -lSDL

game : $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o game $(LIBS)

main.o : Core.h GameStates.h globals.h 
    $(CC) $(CFLAGS) main.cpp $(LIBS)

Core.o : Core.h Core.cpp GameStates.h Intro.h globals.h
    $(CC) $(CFLAGS) Core.cpp $(LIBS)

Intro.o : Intro.cpp GameStates.h Core.h
    $(CC) $(CFLAGS) Intro.cpp $(LIBS)
4

4 に答える 4

1

複数の翻訳単位間で共有されるオブジェクトの場合、ルールは次のとおりです。定義は 1 つだけである必要がありますが、複数の宣言があってもかまいません。

実際には、これは次のことを意味します: put "extern Class object;" あなたの.hファイル、および「クラスオブジェクト;」.CPP ファイルの 1 つに。

たとえばintro、Intro.h を次のように変更します。

class Intro : public GameStates
{
  ... // whatever 
};
extern Intro intro;

次の行を Intro.cpp に追加します。

Intro intro;

同様にcurrentstate、globals.h の場合:

extern GameStates* currentstate;

および 1 つの .CPP で (コンパイラにとってどちらでもかまいません):

GateStates* currentstate = NULL;

Ps makefile が壊れています。-cこれは、リンク ステップに「リンクしない」ことを意味します。これを試して:

OBJS = main.o Intro.o Core.o
CC = g++
DEBUG = -g
CFLAGS = -Wall $(DEBUG)
LIBS = -lSDL

game : $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o game $(LIBS)

main.o : Core.h GameStates.h globals.h 
    $(CC) -c $(CFLAGS) main.cpp

Core.o : Core.h Core.cpp GameStates.h Intro.h globals.h
    $(CC) -c $(CFLAGS) Core.cpp

Intro.o : Intro.cpp GameStates.h Core.h
    $(CC) -c $(CFLAGS) Intro.cpp
于 2012-09-07T18:19:58.467 に答える
1

問題はコードではなく、ビルド システムです。

正常なビルド システムは、オブジェクト ファイルの名前をソース ファイルの名前と一致させます。しかし、あなたはccWxKsO5.oとを持っていcc13Eqmt.oます。さらに悪いことに、ビルド システムは、同じソースから生成された複数のオブジェクトをリンクしようとしているように見えます (おそらく、一部はコンパイラの以前の実行によって作成されたものです)。

tempnamまた、グロビング*.oは C++ プログラムを構築するための合理的な方法ではありません。


まあ、コードの問題もあるかもしれません。しかし、エラー メッセージ内のオブジェクト名がソース ファイルと関連付けられると、それらを見つけて修正するのが 1000 倍簡単になります。

于 2012-09-07T18:33:45.180 に答える
0

currentstateglobals.h では、 externを宣言する必要があります。次に、定義 ( ) を使用して globals.cpp を作成しますGameStates* currentstate = NULL;。コード内に intro や core の参照が見つかりませんでしたが、おそらく同じ問題です: extern を宣言している限り、グローバル変数を何度でも宣言でき、結果のバイナリごとに 1 回だけ定義できます。翻訳単位は 1 つだけです。

また、他に何かを追加する場合に備えて、globals.h にヘッダー ガード (#ifndef GLOBALS_H ...) を追加することをお勧めします。

于 2012-09-07T18:20:49.837 に答える
0

globals.h にインクルード ガードを配置し、GameStates* 宣言を extern にします。

//globals.h
#ifndef _MY_GLOBALS_H_
#define _MY_GLOBALS_H_
#include "GameStates.h"
#include "SDL/SDL.h"

extern GameStates* currentstate;
#endif

//Main.cpp

#include "globals.h"

GameStates* currentState = 0;
于 2012-09-07T18:22:24.503 に答える