Search code examples
c++linkersymbols

Multiple Defined Symbols C++ error


I thought ifndef something #define something body #endif solved this error, so I'm not sure why this is happening.

//Library.h
#ifndef __LIBRARY__
#define __LIBRARY__

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdlib>

//file includes
#include "Globals.h"

using namespace std;

#endif //__LIBRARY__

--

//globals.h
//global variables
#ifndef __GLOBAL__
#define __GLOBAL__

#include <vector>
#include <iostream>
#include <string>

//prototypes
bool Poglathon(std::vector<std::string>& text);
void NPCTalk(std::string const& speaker,std::vector<std::string> const& text);
void wait(double seconds);

//player stats
std::string name;
double str;     //strength
double wis;     //wisdom
double ref;     //reflex
double hp;      //health points
double i;       //initiative
double inte;    //intelligence
double c;       //courage
int gold;       //gold
int xp;         //experience
int ap;         //armour points
int wd;         //weapon damage
int lvl;        //level
int sp;         //skill points

#endif //__GLOBAL__

Then there's two other cpp files that include "Library.h".


Solution

  • The problem is that in your globals.h header file, you're declaring a suite of variables that by default have external linkage: namely, all the globals!

    When you prototype a function in a header file, you are declaring a function, but not defining it. It's perfectly legal to have multiple declarations of the same function, which is why if several different files all #include the same header and declare the same function it's perfectly fine. On the other hand, if you have global variables in a header file, you are defining those variables. Variables can only be defined once in C++ (this is called the one-definition rule), and if multiple files define the same variable or function it will cause a linker error because the linker won't know which version to use. This is the reason, by the way, that you don't #include .cpp files, since if you did you'd multiply define all the functions exported by that header.

    To fix this problem, in the header you'll want to change those variable definitions to variable declarations by using the extern keyword:

    //player stats
    extern std::string name;
    extern double str;     //strength
    extern double wis;     //wisdom
    extern double ref;     //reflex
    extern double hp;      //health points
    extern double i;       //initiative
    extern double inte;    //intelligence
    extern double c;       //courage
    extern int gold;       //gold
    extern int xp;         //experience
    extern int ap;         //armour points
    extern int wd;         //weapon damage
    extern int lvl;        //level
    extern int sp;         //skill points
    

    This will allow any number of files to #include this header, since none of them are actually defining the variables; they're just declaring that the variables will exist somewhere. Then, you should create a new .cpp file, probably globals.cpp, that actually defines the variables:

    #include "globals.h"
    
    std::string name;
    double str;     //strength
    double wis;     //wisdom
    double ref;     //reflex
    double hp;      //health points
    double i;       //initiative
    double inte;    //intelligence
    double c;       //courage
    int gold;       //gold
    int xp;         //experience
    int ap;         //armour points
    int wd;         //weapon damage
    int lvl;        //level
    int sp;         //skill points
    

    These are the actual definitions for the variables, and since they exist in just one place (globals.cpp) you won't get any more linker errors.

    Hope this helps!