SDL — C ++ несколько определений

Я пытаюсь создать эти файлы, но это дает мне многократную ошибку определения.

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;

Извините, если отступ отключен; наличие четырех пробелов для того, чтобы он был виден как блок кода, немного с ним связанный.

Вот сообщение об ошибке:

/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)

0

Решение

Для объектов, совместно используемых несколькими единицами перевода, действует правило: должно быть только одно определение, но у вас может быть несколько объявлений.

На практике это означает: поставить «объект внешнего класса»; в вашем .h файле, и «объект класса;» ровно в одном из ваших файлов .CPP.

За introнапример, измените свой Intro.h на:

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

и добавьте эту строку в Intro.cpp:

Intro intro;

Аналогично для currentstateв globals.h:

extern GameStates* currentstate;

и в одном .CPP (не имеет значения, какой компилятор):

GateStates* currentstate = NULL;

Постскриптум Ваш make-файл поврежден. Вы передаете -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
1

Другие решения

В globals.h вы должны объявить currentstate ехЬегп. Затем создайте globals.cpp с определением (GameStates* currentstate = NULL;). Я не смог найти ссылки на вводную часть или ядро ​​в вашем коде, но это, вероятно, та же проблема: вы можете объявлять глобальные переменные так часто, как хотите, до тех пор, пока вы объявляете их extern, и определять их только один раз для каждого полученного двоичного файла, в только одна единица перевода.

Кроме того, вы, вероятно, захотите добавить защиту заголовка (#ifndef GLOBALS_H …) в globals.h, на случай, если вы добавите туда что-нибудь еще.

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;
0

Проблема не в вашем коде, а в вашей системе сборки.

Любая нормальная система сборки сопоставляет имя объектных файлов с именами исходных файлов. Но у тебя есть ccWxKsO5.o а также cc13Eqmt.o, Что еще хуже, система сборки, похоже, пытается связать несколько объектов, сгенерированных из одного источника (возможно, некоторые были созданы более ранним запуском компилятора).

tempnam и шарить *.o это не разумный способ создания программ на C ++.


Ну, могут быть некоторые проблемы с кодом. Но их будет легче найти и исправить в тысячу раз, как только имена объектов в сообщениях об ошибках соотносятся с исходными файлами.

0
По вопросам рекламы [email protected]