views:

190

answers:

3

I want to declare string constants that will be used across various classes in the project. I am considering two alternatives

Option 1:

#header file 
class constants{
    static const string const1;
};

#cpp file

const string constants::const1="blah";

Option 2:

#header file 
namespace constants{
    static const string const1="blah";
};

Just wondering what would be a better implementation.

Already looked at

http://stackoverflow.com/questions/3299765/where-to-store-class-specific-named-constants-in-c

http://stackoverflow.com/questions/2465546/where-to-put-constant-strings-in-c-static-class-members-or-anonymous-namespace


UPDATE:

Option 3:

Based on the suggestions from "potatoswatter" and "sellibitze" i currently have the following implementation?

#header file
namespace constants{
    extern const string& const1(); //WORKS WITHOUT THE EXTERN  ***WHY***
};

#cpp file
namespace constants{
   const string& const1(){static string* str = new string ("blah"); return *str;}
}

I'm including the header file where i need to use the constants. Are there any major cons of this implementation?

+2  A: 

Option 1 achieves the same as Option 2, but in a messier way.

If you're going to use a class that just has static members, especially for global access/constants, use a namespace.

The Communist Duck
+5  A: 

Option 2 doesn't appear to be a solution. The strings will still be defined separately for each source file, despite appearing in the same namespace.

So then Option 1 is better, but I don't like using a class as a namespace.

Try using extern:

#header file 
namespace constants{
    extern const string const1;
}

#cpp file

const string constants::const1="blah";

Note that this may run afoul of the Static Initialization Order Fiasco unless you ensure that the string literal source is compiled/linked/initialized first, which is implementation-dependent.

The easier way is just to use C string literals. If you want blah, write "blah". Is this part of a localization system or something?

Potatoswatter
It'll be cleaner in the presence of multiple constants to use namespace constants { ... } in the source file.
pkh
@Potatoswatter: $2.13.4/2- Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementationdefined. The effect of attempting to modify a string literal is undefined. So even if they are defined separately, they may not really occupy as much distinct space in memory if that was the concern.
Chubsdad
@Chubsdad: The only string literals in OP's code are the initializers to `std::string`. I was referring to the `std::string` objects.
Potatoswatter
@Potatoswatter: When u say use c string literals are you suggesting that i replace the std::string with char*? Also how would i avoid the Static Initialization Order Fiasco?
Shishya
Potatoswatter
@Potatoswatter: Localization is not a concern to me for this project. But i'm c++ newbie, so im not quite clear on why switching to char* would solve the SIOF problem.
Shishya
@Shishya: `std::string` is an object with a constructor, so it's invalid before the constructor is called. On the other hand, a string literal is just raw data built into the application binary, and it's required to be valid before any C++ code runs at all. Being initialized by the OS, not C++, it's completely outside the SIOF.
Potatoswatter
@Potataswatter: please comment on the update where i have listed my current impl based on your suggestion.
Shishya
A: 

Neither. I'd go with this:

// header file
namespace constants {
extern const char const1[];
}

// cpp file
namespace constants {
extern const char const1[] = "blah";
}

The header file contains a declaration of const1 with incomplete type but convertible to char const* and the cpp-file contains a definition of the character array with external linkage. There is no dynamic initialization like you have with std::string. So, that's a plus, IMHO.

sellibitze
Shouldn't the code in the .cpp be this instead? `const char constants::const1[] = "blah";`, ie: no `extern` and no `namespace` redeclaration.
Remy Lebeau - TeamB
@Remy: *shrug*. Do whatever you like. But there's nothing wrong with the code I posted. You can remove `extern` in the cpp file if you include the header which already declares `const1` to have external linkage. But since in C++ constant variables at namespace scope have internal linkage by default you need to have at least one `extern` in there. What I posted also works without including the header in the cpp file, btw.
sellibitze