24

Possible Duplicate:
C++ static constant string (class member)
static const C++ class member initialized gives a duplicate symbol error when linking

My experience with C++ pre-dated the addition of the string class, so I'm starting over in some ways.

I'm defining my header file for my class and want to create a static constant for a url. I'm attempting this by doing as follows:

#include <string>
class MainController{
private:
    static const std::string SOME_URL;
}

const std::string MainController::SOME_URL = "www.google.com";

But this give me a duplicate definition during link.

How can I accomplish this?

1

4 Answers 4

21

Move the

const std::string MainController::SOME_URL = "www.google.com";

to a cpp file. If you have it in a header, then every .cpp that includes it will have a copy and you will get the duplicate symbol error during the link.

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

2 Comments

I guess what I don't quite understand is that I have these within my header guards. This fixed the problem, I just don't understand why...
@Thom, the problem is not solved with the headers guards because each translation unit (cpp file) includes the header so each translation unit ends up with a 'copy' of the string with the same name, the result is that each translation unit compiled correctly. However when linking multiple translation units have the same symbol (the string) and that provoke the link error due to the symbolic link.
12

You need to put the line

const std::string MainController::SOME_URL = "www.google.com";

in the cpp file, not the header, because of the one-definition rule. And the fact that you cannot directly initialize it in the class is because std::string is not an integral type (like int).

Alternatively, depending on your use case, you might consider not making a static member but using an anonymous namespace instead. See this post for pro/cons.

13 Comments

@Nawaz In practice. Formally, multiple definitions in difference translation units is undefined behavior, so a compiler could make it work. (Or do anything else, but "make it work" was a common implementation in C. Where constructors didn't enter into it.)
@JamesKanze: What are you trying to say? That it has to do with type of the static member?
@Nawaz: I know that's not what the OP is doing. The OP mentions he is rusty in C++. I am merely adding some information as to how to initialize the string (put it in the cpp), that if it was an int it could be initialized directly in the class body, and that an anonymous namespace might be useful in some cases.
@Nawaz It has nothing to do with the type. Multiple definitions in separate translation units is undefined behavior, and a compiler is allowed to make it work. Traditionally, C compilers did (for historical reasons); C++ compilers haven't. Probably because with older linkers, it's very difficult to make it work when there is dynamic initialization. In practice, with a C++ compiler, you will get an error.
@Nawaz I wasn't trying to say that you were wrong; for all intents and purposed, today in C++, you're right. I was just throwing in some additional information: historical and standardese, but nothing to change the impact of what you had written.
|
4

Define the class in the header file:

//file.h
class MainController{
private:
    static const std::string SOME_URL;
}

And then, in source file:

//file.cpp
 #include "file.h"

const std::string MainController::SOME_URL = "www.google.com";

Comments

2

You should put the const std::string MainController::SOME_URL = "www.google.com"; definition into a single source file, not in the header.

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.