The multiple definition thing is due to you giving the variable multiple "bodies". It's easier to visualize with functions, so let me use that as an analogy.
If you put a function body in a header file and #include that header file in two separate cpp files, you will get the same error. The reason for this is because each cpp file is compiled individually, then the compiled function bodies are "linked" together to form the final executable. If the same function has bodies in two different cpp files, then the linker gets confused because it sees two cpp files giving a body for the same function and it doesn't know which one to use.
To get around the issue, you declare a "prototype" in the header, then define the "body" in only one cpp file.
1 2 3
|
//myfunction.h
int myfunction(); // the prototype
|
1 2 3 4 5 6 7
|
//myfunction.cpp
#include "myfunction.h"
int myfunction() // the function body
{
// do some stuff here
}
|
Global variables are the same way. When you make a global variable, you are telling the compiler to reserve some memory for that variable. The linker then combines all those variables together in the final executable. But if two different cpp files are giving it two different variables to use with the same name, it gets confused.
In this sense, the "extern" keyword is a lot like a prototype. It tells the compiler that the variable exists somewhere, but doesn't actually create it. It's assumed that the linker will "fill in" the body after all the cpp files have been compiled.
1 2 3
|
// myglobal.h
extern int myglobal; // the variable "prototype"
|
1 2 3 4
|
// myglobal.cpp
#include "myglobal.h"
int myglobal = 0; // the variable "body"
|
EDIT:
That said... global variables are
ATROCIOUS and you should really avoid using them. They severely cripple your code and make program management and maintenance much more difficult. They may seem simpler for small program, but as your program gets larger, they will make things more and more unwieldly.
They also get you in the practice of writing crappy code that is not reusable. When your code works with a global... it
ONLY works with that global. When your code works with parameters, it can work with
ANYTHING, making it much more functional and much more reusable.
Here's a classic example. Let's say you're writing a simple game and have a player fighting a goblin. You decide to have player and goblin life/hp stored as global variables.
Then you write a function to damage the player:
1 2 3 4 5 6 7 8 9
|
int playerhp = 100;
int goblinhp = 20;
// hurts the player, returns true if the player is still alive, false if the player is dead
bool HurtPlayer( int damage )
{
playerhp -= damage;
return (playerhp > 0);
}
|
Seems fine, right?
The problem is... that function only works with the player. Say you want to do the same thing with the goblin. You now have to write an entirely separate function:
1 2 3 4 5 6
|
// likely just a copy/paste of HurtPlayer
bool HurtGoblin( int damage )
{
goblinhp -= damage;
return (goblinhp > 0);
}
|
Now what happens when you want to add more enemies? Or more players? Do you copy/paste this function for all of them? What if you want to change how these functions work (to add some kind of defense calculation or something). Do you go back and change each and every one of the dozen identical functions?
Because you used globals, the functions can only be used with those globals. It makes them extremely restrictive.
Compare that to a function that uses no globals:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
bool DamageObject( int& objecthp, int damage )
{
objecthp -= damage;
return (objecthp > 0);
}
//...
int main()
{
// to damage the goblin
DamageObject( goblinhp, 5 );
// to damage the player
DamageObject( playerhp, 4 );
// etc
|
And that's just
one example of why globals are horrible. There are many more.