C++ Link Error with namespaces and include files

Go To StackoverFlow.com

0

I'm working on the core of my engine and i'm having a serious link issue in Microsoft Visual c++ express.

To simplify things, what is causing problems is these two header files and each header file has a namespace with a different identifier. Both of these include files actually include each other. No error is obtained from compiling, however on linking, an error shows up saying "X already defined in A.obj". An example is provided below:

HEADER 1

#ifndef HEADER1_H
#define HEADER1_H

#include "header2.h"
namespace Core{
    int x, y, z;
}
#endif

HEADER 2

#ifndef HEADER2_H
#define HEADER2_H

#include "header1.h"
namespace GUI{
    int x, y, z;
}
#endif

What ends up happening is I get an error stating that the x, y, and z variables were already defined in the first .obj file that was created. I assumed that because the variables are from different namespaces they could not collide. I have header guards as well so the header files don't seem to be included multiple times.

Anyways, any sort of help or advice would be greatly appreciated. I've been stuck on this for around 3 days :P. Also, please let me know if I'm not giving enough information, it is just that my current code is extremely long.

Cheers, Joey

2012-04-05 00:25
by Joseph Pla
The short answer is: don't have headers that include each other - Oliver Charlesworth 2012-04-05 00:27
Alright, yes I had a feeling that it could lead to some problems, however how could I go about having the cpp of header 1 have access to header 2 AND vice versa. Or is that a serious flaw in my design - Joseph Pla 2012-04-05 00:30
They can't have "direct" access to each other. So perhaps you'll need some forward declarations somewhere - Oliver Charlesworth 2012-04-05 00:31
Ah, I just searched it up and it seems to be a good solution. Thank you so much Oli : - Joseph Pla 2012-04-05 00:33
Why are you declaring variables in header files - Jim Rhodes 2012-04-05 00:36
I wanted them to be globals but part of namespaces. I'm guessing that is a terrible idea : - Joseph Pla 2012-04-05 00:40
@Jim : What's wrong with declaring variables in header files ("globals are bad" aside)? Defining them in header files on the other hand.. - ildjarn 2012-04-05 01:24


8

Actually, the problem is that the variables are defined in the header files- it's not that the header files include, is that in each .cpp files that includes the header, all 6 variables are being defined.

Each .cpp file turns into a .o file, and each .o ends up with the variables being defined, which causes the linker errors. What you want to do is use the extern keyword in the headers, that tells the compiler the actually variable is defined elsewhere...

for instance:

namespace Core{
    extern int x, y, z;
}

and

namespace GUI{
    extern int x, y, z;
}

then, in a cpp file ( in only one cpp file! ) you need define the variable without the extern

namespace Core {
    int x, y, z;
}
namespace GUI{
    int x, y, z;
}

that will fix your linker errors.

2012-04-05 00:41
by Joshua Glazer
Perfect Joshua, I could not have asked for a better answer. I just tried it and no more error. Thanks a ton! : - Joseph Pla 2012-04-05 00:48


1

The problem is not that you're including the same variable names in multiple namespaces, it's that you're defining the variables in a header rather than just declaring them. This makes the compiler create one copy of those variables for each of the compilation units that includes the header, and these conflict at link time, which is why you get errors.

Use extern to just declare them in the headers, rather than defining them:

HEADER 1

#ifndef HEADER1_H
#define HEADER1_H

#include "header2.h"
namespace Core{
    extern int x, y, z;
}
#endif

HEADER 2

#ifndef HEADER2_H
#define HEADER2_H

#include "header1.h"
namespace GUI{
    extern int x, y, z;
}
#endif

And then in the respective .cpp files for your two headers, put your namespace Core { int x, y, z; } and namespace GUI{ int x, y, z; }

2012-04-05 00:39
by je4d
Does that mean I'm declaring the namespace in both the header and the cpp - Joseph Pla 2012-04-05 00:43
@JoeyPla You don't have to declare the whole namespace in one go - you can have multiple places where you write namespace Foo {... }, and the contents accumulat - je4d 2012-04-05 00:45
Alright thanks - Joseph Pla 2012-04-05 00:56
Ads