Joe
Joe

Reputation: 1101

Why does removing const give me linker errors?

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?

Upvotes: 1

Views: 437

Answers (5)

anon
anon

Reputation:

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

Upvotes: 3

Dave Gamble
Dave Gamble

Reputation: 4174

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

Upvotes: 2

Klaim
Klaim

Reputation: 69682

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.

Upvotes: 1

Not Sure
Not Sure

Reputation: 5963

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";

Upvotes: 5

Michael
Michael

Reputation: 55415

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.

Upvotes: 5

Related Questions