tags:

views:

195

answers:

5

I have a global variable:

const std::string whiteSpaceBeforeLeadingCmntOption = "WhiteSpaceBeforeLeadingComment";

When I remove the const on this variable declaration, I get many occurrences of the following linker error:

error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > whiteSpaceBeforeLeadingCmntOption" (?whiteSpaceBeforeLeadingCmntOption@@3V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in REGISTER_TO_UNSRLZ.obj

This is in a .h file, which is included various places, but I have a #ifndef band on it to avoid including it in several places. Any ideas what the error is from?

+5  A: 

This works when you have const in the .h, since const implies static so you can have the same variable in multiple compilands.

By removing const on a variable defined in a .h file, you are creating multiple instances with the same identifier within the same program.

If you need to remove const, in the .h, you could do:

extern std::string whiteSpaceBeforeLeadingCmntOption;

And then have:

std::string whiteSpaceBeforeLeadingCmntOption = "";

In one of your .cpp files.

Michael
+1 for beating me to it
Not Sure
+5  A: 

The problem is that by defining it in the header file, it is being instantiated in each compilation unit that includes that header file, leading to it being multiply defined for the link stage.

What you want to do is declare this in your .h:

extern std::string whiteSpaceBeforeLeadingCmntOption;

And then in a single cpp, declare:

std::string whiteSpaceBeforeLeadingCmntOption = "WhiteSpaceBeforeLeadingComment";
Not Sure
+1  A: 

Because if your header is included in several cpp files, then you have multiple definitions of the same variable (here a global). It's forbidden by the language.

What you want is to separate the declaration and the definition :

header :

extern std::string whiteSpaceBeforeLeadingCmntOption; // declaration
// the 'extern' keyword is here to be sure the linker will look in all cpp for the definition of this variable

in one cpp :

std::string whiteSpaceBeforeLeadingCmntOption = "WhiteSpaceBeforeLeadingComment"; // definition

That's true for class static variables too.

But if the object is const then the compiler will only make one definition of the const object and put it somewhere in read only memory. You don't have to specify in witch compilation unit it is defined.

Klaim
+2  A: 

The #ifndef sentinel will only prevent each FILE from including it more than once.

Dave Gamble
In the answer FILE should be read as 'compilation unit'. +1 as it is a common mistake.
David Rodríguez - dribeas
+3  A: 

In C++ the names of const objects are local to the compilation unit they occur or are #included in.

anon