Global vars in header file

Started by
2 comments, last by Alexistran 17 years, 5 months ago
I'm in the process of creating a simple text RPG game and I'm now trying to clean up some of my code by separating the source into more files. In the process of trying to split 'battle.cpp' the file containing all functions related to (you probably guessed it) battling into more files I moved all the global variables and prototypes to a new header file, however these global variables were not constant and were declared and defined at the same time

#ifndef BATTLE_DEF
#define BATTLE_DEF
int bonushit, bonushealth, bonusmana, bonusevade, bonusdmg, bonusspelldmga = 0;
int bonusdmgtype, bonusspelldmgbytype = -1;
float bonuscost = 10;
int bonusspelldmgm = 100;
int defreturn = 0;
#endif




However when I try and compile I get told that:

>battle_phases.obj : error LNK2005: "int bonusdmgtype" (?bonusdmgtype@@3HA) already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonushealth" (?bonushealth@@3HA) already defined in battle.obj
2>battle_phases.obj : error LNK2005: "bool scanned" (?scanned@@3_NA)
 already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonusevade" (?bonusevade@@3HA) already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonusdmg" (?bonusdmg@@3HA) already 
defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonushit" (?bonushit@@3HA) already
 defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonusmana" (?bonusmana@@3HA) already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonusspelldmga" (?bonusspelldmga@@3HA)
 already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonusspelldmgbytype" (?bonusspelldmgbytype@@3HA) 
already defined in battle.obj
2>battle_phases.obj : error LNK2005: "float bonuscost" (?bonuscost@@3MA) 
already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int bonusspelldmgm" (?bonusspelldmgm@@3HA)
 already defined in battle.obj
2>battle_phases.obj : error LNK2005: "int defreturn" (?defreturn@@3HA) already defined in battle.obj
Any ideas what I'm doing wrong?
Advertisement
Yup. When you compile, each .cpp is compiled independently, to create object files (usually .obj). These files are then linked together by the linker, and any references from one object file to a variable, function, and so forth that is not in the same object file is linked to the object file that does contain it.

Your problem is with putting the definition in a header file. Every .cpp that includes that header file ends up defining that variable (#ifdef/#define/#endif inclusion guards only ensure that you don't declare things multiple times per translation unit, i.e., .cpp file). Thus, the variable is located in multiple object files, and the linker doesn't know which one to use.

The solution: Use the extern keyword in front of the variable type/name in the header file, and leave out the initial value. In any .cpp file that includes the header (but only one .cpp), put what you currently have in the header file in there (no extern keyword, but with initial value, if you don't want 0). You can even make a new .cpp file if you want. Call it globals.cpp or something. Just make sure that the definition only occurs in one single translation unit, so that the linker doesn't get confused by multiple identical looking variables/functions.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
If you haven't done so already, take a look at this article: Organizing Code Files in C and C++.

You'll need to precede the global variable declarations in the header file with the extern keyword, and put the variable definitions in a .cpp file.
Thanks for the help, its now working.

This topic is closed to new replies.

Advertisement