1

So I have a nested namespace in a header file. Inside the namespace I have some standalone data. However on compile, I get a "already define in <..>.obj". I tried messing around with inline but apparently inline only works with functions. Here is my code:

#ifndef HEADER_H #define HEADER_H namespace sod { namespace e { const int _2D = 0; const int _3D = 1; const int _CUSTOM = 2; const char *text1 = "I AM A C STRING"; // <-- char const * const sod::e::text1 (?text1@e@sod@@3PBDB) already defined in main.obj const char *text2 = "I AM ALSO A C STRING"; // <-- char const * const sod::e::text2 (?text2@e@sod@@3PBDB) already defined in main.obj }; }; #endif 

The editor I am using is Visual Studio 2017.

Any help is appreciated.

5
  • #indef? Or do you mean something else? Commented Jun 9, 2018 at 19:03
  • 1
    If you include it into multiple object files it will of course exist in all of them. Compiler works on single source file at a time so the defines work that way also. This belongs to a single object file, headers might have extern definitions for it thoug Commented Jun 9, 2018 at 19:04
  • #ifndef Sorry, typo. Fixed now. Commented Jun 9, 2018 at 19:04
  • Include guards are not related in any way to linking issues. For linking issues it doesn't matter whether you have them or not. It still makes no sense to define objects with external linkage in header files. Commented Jun 9, 2018 at 19:32
  • What is your intent? Ars these two pointers supposed to be changeable or constant? Commented Jun 9, 2018 at 19:48

2 Answers 2

3

Your integer constants have internal linkage, since they are declared const. Specifically because of this they do not produce multiple definition errors even when this header file is included into multiple translation units.

Your string pointers have external linkage, since they are not declared const. Because of this you end up with multiple definition errors when this header file is included into multiple translation units. You are not allowed to have multiple non-inline definitions of objects with external linkage in your program.

If you intended your string pointers to be const, just like your integers, you should have declared them as such

const char *const text = "whatever"; 

Note where the extra const is placed in the declaration.

But if you intended your pointers to be modifiable global variables, then it is a different story. In C++17 compilers you can achieve that by simply adding inline

inline const char *text = "whatever"; 

In pre-C++17 you'd have to jump through a more complicated combination of hoops with extern declarations in header file. (Do a search here for topics about global variables - it is well covered on SO.)

P.S. Include guards have nothing to do with avoiding linker errors.

Sign up to request clarification or add additional context in comments.

Comments

1

Someone posted the right answer that helped me, but I think they deleted the post.

The simple answer is to use extern.

In my header file:

#ifndef HEADER_H #define HEADER_H namespace sod { namespace e { extern const int _2D; extern const int _3D; extern const int _CUSTOM; extern const char *text1; extern const char *text2; }; }; 

In the cpp file:

#include "header.h" namespace sod { namespace e { const int _2D = 0; const int _3D = 1; const int _CUSTOM = 2; const char *text1 = "I AM A C STRING"; const char *text2 = "I AM ALSO A C STRING"; }; }; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.