linker errors, already defined in an another object

so i creadted this 2d game using sdl it worked fine, but then when i started optimizing it, seperating the header files and the cpp files, there were no errors but the linker is shouting too much, iknow that u cant inlcude multiple definition, but some of the ftns doesnt work withouth inlcudig the other file, any help/ suggestions

main.cpp
1
2
3
4
5
6
7
8
#include "globals.h"
#include "Characters.h"
#include "Fighters.h"
#include "variables.h"


Fighters game;
int main(int argc, char** argv);

globals.h // global variables needed every where inthe game
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL_mixer.h>
using namespace std;
//destination for the selected players imagese
SDL_Rect pic1;

SDL_Rect instrect = { 100,100,700,500 };

SDL_Window* gwindow = NULL;
SDL_Renderer* grender = NULL;

const int window_width = 900;
const int window_height = 700;

//main menu background animation system
double background_images = 0;

//keys info
bool keys[332];

enum Music_for { moves, special_moves };
enum State { main_menu, fighting };
State state;

bool is_running = true;
SDL_Event main_event;

int ticks_for_caping_fps = 0;
const int fps = 60;
int frametime = 0;

bool sound_flag = false;
Mix_Chunk* punch;
Mix_Chunk* kick;
Mix_Music* win;

//for players size
SDL_Rect grect = { 0,0,150,300 };

//idle//walking//punch//kick//jump//death//special
double subzero_flags[11] = { 0 };

//idle//walkback//walkfront//punch//kick//jump//death//combo//
double ryo_flags[11] = { 0 };

//to know which players are selected
string player_selected[2] = { "" };

//if both are selected then onthe start the game
bool both_player_selected = false;
bool flag[4] = { false };

void render(int x, int y, SDL_Texture* tex, SDL_Rect* clip) {
	//Set rendering space and render to screen
	SDL_Rect renderQuad = { x, y, 200, 120 };

	//Set clip rendering dimensions
	if (clip != NULL) {
		renderQuad.w = clip->w;
		renderQuad.h = clip->h;
	}
	SDL_RenderCopy(grender, tex, NULL, &renderQuad);
}

SDL_Rect health1_rect;
SDL_Rect health2_rect;

bool won = false;

//texts to appear when a player is selected
SDL_Texture* subzero_selected = NULL;
SDL_Texture* lori_selected = NULL;

//for color keying
SDL_Surface* colorkey1 = NULL;

//winning text
SDL_Texture* win1 = NULL;

//play again
bool again = true;
bool first_player_selected = false;
bool second_player_selected = false;

bool check_if_both_players_selected(SDL_Event event, State state) {
	if (state == main_menu) {
		if (event.type == SDL_KEYDOWN) {
			if (event.key.keysym.sym == SDLK_1) {
				flag[0] = true;
				flag[1] = false;
				player_selected[0] = "lori";
			}
			else if (event.key.keysym.sym == SDLK_2) {
				flag[1] = true;
				flag[0] = false;
				player_selected[0] = "sub-zero";
			}
			else if (event.key.keysym.sym == SDLK_8) {
				player_selected[1] = "ryo";
				flag[2] = true;
				flag[3] = false;
			}
			else if (event.key.keysym.sym == SDLK_9) {
				player_selected[1] = "scorpio";
				flag[3] = true;
				flag[2] = false;
			}
		}

		//checking if both players are selected
		if (flag[0] == true || flag[1] == true) {
			first_player_selected = true;
		}
		if (flag[2] == true || flag[3] == true) {
			second_player_selected = true;
		}

		if (first_player_selected == true && second_player_selected == true &&
			main_event.key.keysym.sym == 13) {
			both_player_selected = true;
		}
	}
	return both_player_selected;
}


fighter.h //engine of the game
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include"globals.h"
#include"Characters.h"
#include"variables.h"

class Fighters {
private:
	vector<SDL_Texture*> background;
public:
	int initialize();
	void load_main_menu();
	void start_game(SDL_Event ev);
	void close();
	void won_check();
};

character.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#pragma once
#include"globals.h"

class Character {
	vector<SDL_Texture*> sprites;
	int player1_x_posiotion = 0, player1_y_posiotion = 0;
	int player2_x_posiotion = 0, player2_y_posiotion = 0;

	int mVelX1 = 0, mVelY1 = 0;
	int mVelX2 = 0, mVelY2 = 0;
public:
	static const int player_width = 150;
	static const int player_height = 300;

	//Maximum axis velocity of the dot
	static const int player_velocity = 6;

	Character() :player1_x_posiotion(300), player2_x_posiotion(500) {}
	void create_player(string player_name);
	SDL_Texture* getsprite(int no);
	void handleEvent(SDL_Event& e);
	void walk1();
	//walk for character 2
	void walk2();
	void move();
	void delete_characters();
	void reset();
};

music.h
1
2
3
4
5
6
7
8
9
10
#pragma once
#include "globals.h"
class Music {
	Mix_Music* background_music = NULL;
	Mix_Chunk* sound_affect = NULL;
public:
	int load_background_music(State state);
	bool load_sound_effect(const string& path, int repetition = 0);

};


and lastly some other variables that i needed, to get rid of some errors
variables.h
1
2
3
4
5
6
7
#pragma once
#include "Characters.h"
#include "Music.h"
Character player1;
Character player2;
Music gb_music;
Music gfight_sound;


well i tried almost everything, or its just that cause im dumb, but it looks like thers no way, so any suggestion or mind opening tips would help, thanks

Last edited on
post the error message...
its not that you are dumb, its that you appear to have jumped into graphics and game coding with minimal background in the basics. The trial by fire approach can be fun and informative, but when things go wrong, you don't have anything to fall back on to fix it.
A variable can only be defined once. #pragma once protects against multiple inclusion in the same compilation unit - but not between multiple compilation units.

One and only one compilation unit defines the variables. The other compilation units that use these variables marks them as extern.

eg

in main.cpp:

 
Character player1;


in another.cpp:

 
extern Character player1;


This still compiles OK but now when it comes to linking, the linker knows that player1 is defined elsewhere and not to try to re-define it.
there were no errors but the linker is shouting too much


Unless I'm misunderstanding you, you mean that the linker is reporting errors, yes? Which makes your "no errors" comment somewhat baffling.

Also, if you have error messages, tell us what they are, rather than just dropping hints that you have some.

The problem is with all the global variables you're defining in globals.h. That file is getting included in every source file, which means that those globals are being defined in every single translation unit. Hence, multiple definitions.

This doesn't apply to const globals; in C++, those have internal linkage only, so you can have those definitions in multiple units.

some of the ftns doesnt work withouth inlcudig the other file


The first thing to say about using non-const global variables, is: as much as possible, DON'T. They're problematic in all sorts of ways (and I'm sure you can find explanations why in less time than it would take me to type them). If your functions need certain variables to work, then pass them as arguments. If your classes need certain variables to persist, then make them data members of that class.

If you really, really need a global variable (and you probably don't), and it's not const, then you need the definition in one place, and one place only - so not a header file - and then you need an extern declaration of that global in the other places that need to use it.

So, in one source file, you want:

Character player1;

Then in a header file:

extern Character player1;
Last edited on
speaking of classes, one way to solve it is to put your globals into a class/struct, create one of them in main, and pass it to everything else in a blob. still not a great design, but it would do minimal damage to what you have already done.
o so i solved my problem by using public variable in classes. but I still have no grasp of this concept, cause there was this code that was showing same linker errors on vs 2019 but it ran just fine on vs code, like why?
there was this code that was showing same linker errors on vs 2019 but it ran just fine on vs code, like why?


Well, like there was this compiler that worked, see.

By the way, I'm feeling a little bit ill. What's wrong with me?
lol, so basically theres a different linker for every different compiler, and is there a way to use mingw in vs 2019.



and btw get checked up, you'll be alright
so basically theres a different linker for every different compiler, and is there a way to use mingw in vs 2019.


I don't know the answer, but that is a way better question than before. Even better would be is you posted some of the actual error messages, which @jonnin and @MikeyBoy both requested.

You're telling us it won't link. All we can tell you with that information is that your linker doesn't like the code you gave it. We can't tell you what the problem is if you don't tell us what the symptoms are.

It's kind of like posting on a message board

By the way, I'm feeling a little bit ill. What's wrong with me?


If you don't post error messages, you're not going to get any worthwhile help.
wtf is wrong with, lol.
but the thing is I cant post them anymore, cause the codes fixed and there were like 350+ errors msgs so i didn't want to bombard them here.

so sorry
but heres the other code that i talked about that worked fine on vs code but not on vs studio 2019, so here all the linker error msgs, if anyone still willing to help me with that


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Severity	Code	Description	Project	File	Line	Suppression State
Error	LNK2005	"public: __cdecl Asteroid::Asteroid(void)" (??0Asteroid@@QEAA@XZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: __cdecl LButton::LButton(void)" (??0LButton@@QEAA@XZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: __cdecl LTexture::LTexture(void)" (??0LTexture@@QEAA@XZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: __cdecl LTimer::LTimer(void)" (??0LTimer@@QEAA@XZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: __cdecl Particle::Particle(int,int)" (??0Particle@@QEAA@HH@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: __cdecl Asteroid::~Asteroid(void)" (??1Asteroid@@QEAA@XZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: __cdecl LTexture::~LTexture(void)" (??1LTexture@@QEAA@XZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTexture::free(void)" (?free@LTexture@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: int __cdecl LTexture::getHeight(void)" (?getHeight@LTexture@@QEAAHXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: unsigned int __cdecl LTimer::getTicks(void)" (?getTicks@LTimer@@QEAAIXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: int __cdecl LTexture::getWidth(void)" (?getWidth@LTexture@@QEAAHXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LButton::handleEvent(union SDL_Event *)" (?handleEvent@LButton@@QEAAXPEATSDL_Event@@@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: bool __cdecl Particle::isDead(void)" (?isDead@Particle@@QEAA_NXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: bool __cdecl LTimer::isPaused(void)" (?isPaused@LTimer@@QEAA_NXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: bool __cdecl LTimer::isStarted(void)" (?isStarted@LTimer@@QEAA_NXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: bool __cdecl LTexture::loadFromFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?loadFromFile@LTexture@@QEAA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: bool __cdecl LTexture::loadFromRenderedText(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct SDL_Color)" (?loadFromRenderedText@LTexture@@QEAA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@USDL_Color@@@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTimer::pause(void)" (?pause@LTimer@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl Asteroid::render(void)" (?render@Asteroid@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LButton::render(void)" (?render@LButton@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTexture::render(int,int,struct SDL_Rect *,double,struct SDL_Point *,enum SDL_RendererFlip)" (?render@LTexture@@QEAAXHHPEAUSDL_Rect@@NPEAUSDL_Point@@W4SDL_RendererFlip@@@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl Particle::render(void)" (?render@Particle@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTexture::setAlpha(unsigned char)" (?setAlpha@LTexture@@QEAAXE@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTexture::setBlendMode(enum SDL_BlendMode)" (?setBlendMode@LTexture@@QEAAXW4SDL_BlendMode@@@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTexture::setColor(unsigned char,unsigned char,unsigned char)" (?setColor@LTexture@@QEAAXEEE@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LButton::setPosition(int,int)" (?setPosition@LButton@@QEAAXHH@Z) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTimer::start(void)" (?start@LTimer@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTimer::stop(void)" (?stop@LTimer@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"public: void __cdecl LTimer::unpause(void)" (?unpause@LTimer@@QEAAXXZ) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct SDL_Window * gWindow" (?gWindow@@3PEAUSDL_Window@@EA) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct SDL_Renderer * gRenderer" (?gRenderer@@3PEAUSDL_Renderer@@EA) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct _Mix_Music * gMusic" (?gMusic@@3PEAU_Mix_Music@@EA) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct Mix_Chunk * gJet" (?gJet@@3PEAUMix_Chunk@@EA) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct Mix_Chunk * gHot" (?gHot@@3PEAUMix_Chunk@@EA) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct _TTF_Font * gFont" (?gFont@@3PEAU_TTF_Font@@EA) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"struct SDL_Rect * gSpriteClips" (?gSpriteClips@@3PAUSDL_Rect@@A) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"class LTexture gDotTexture" (?gDotTexture@@3VLTexture@@A) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	
Error	LNK2005	"class LTexture gAsteroid" (?gAsteroid@@3VLTexture@@A) already defined in asteroid.obj	V	C:\Users\giberish\Desktop\V\V\game.obj	1	


Assuming the normal scenario in which you have game.cpp which compiles down to game.obj and asteroid.cpp which compiles down to asteroid.obj ...

Well, these linker errors have nothing to do with the code you posted above.

I suspect that in game.cpp you have the following statement: #include "asteroid.cpp" (or vice versa).

When that's the case, everything defined asteroid.cpp is also defined in game.cpp. So you have multiple definitions of the same tokens. Only include header files. Never include source files.

If you show me game.cpp and asteroid.cpp I might be more specific.

Next time, don't go 2 days without posting the error messages.
im just gonna show the inclusions cause the code is just too big

game.cpp has
#include "screen.cpp"

screen.cpp has
#include "spacecraft.cpp"

spacecraft.cpp has
#include "../hpp_files/spacecraft.hpp"

spacecraft.hpp has
#include "../cpp_files/asteroid.cpp"

asteriod.cpp has
#include "../hpp_files/asteroid.hpp"

asteriod.hpp has
#include "../cpp_files/particle.cpp"

particle .cpp has
#include "../hpp_files/particle.hpp"

particle.hpp has
#include "../cpp_files/menu.cpp"

menu.cpp has
#include "../hpp_files/menu.hpp"

menu.hpp has
#include "../cpp_files/timer.cpp"

timer.cpp has
#include "../cpp_files/texture.cpp"

texture.cpp has
#include "../hpp_files/texture.hpp"

texture.hpp has
#include "SDL_files.hpp"

sdl_files.hpp has
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <SDL_ttf.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include <ctime> ///and some other global variables in it


so these are basically all the files








Last edited on
The body of the class functions can only be included once if they are not part of the class definition. If the class is split into a header file containing the class definition and a class implementation file, then only the header file is included in other compilation units.

If you have this (say test.cpp):

1
2
3
class mytest {
    mytest() {}
};


Then that is OK and can be included elsewhere.

If you have:

1
2
3
4
5
class mytest {
    mytest();
};

mytest::mytest() {}


Then that is not. This will give the 'already defined' link error when this is included with multiple compilation units.
Your include statements should ONLY be #include "something.hpp"

For any included file, if the suffix is .cpp, change it to .hpp. That should take care of most of your issues.

NEVER include a .cpp file in another .cpp file.*

When that is resolved, you can start working on other problems you encounter.


* There may be rare cases where it can be done, but this should only be done by an expert who understands what's going on and has an incredibly strong need to do so, and then only after considering all other options first. And even then a redesign is probably preferred.
Changing the suffix of an include file has no effect - any suffix can be used. The only time a suffix has meaning is for the compilation unit file.
@seeplus,

And when the included file has the suffix of a compilation unit file (.cpp), then you start including one compilation unit inside another compilation unit. When those get linked, you get multiple definition problems--exactly what the @OP is experiencing.

I've created my own special suffixes for include files--specifically .tcpp for template "source" files included in a template header file. But that's a more advanced, subtle topic than what is being discussed here.
The problem with multiple definitions is with the contents of the included file - not the file suffix. If the OP wants to do it like this, mark all the functions et al in the included files as inline, then you don't get the multiple definition issue.

Last edited on
Topic archived. No new replies allowed.