Should constant strings be static data members, or should they be in an unnamed namespace?

12.9k Views Asked by At

I need to define some constant strings that will be used only by one class. It looks like I have three options:

  1. Embed the strings directly into locations where they are used.

  2. Define them as private static constant members of the class:

    //A.h
    class A {  
    private:  
       static const std::string f1;  
       static const std::string f2;  
       static const std::string f3;  
    };  
    
    //A.cpp  
    const std::string f1 = "filename1";  
    const std::string f2 = "filename2";  
    const std::string f3 = "filename3";  
    
    //strings are used in this file  
    
  3. Define them in an unnamed namespace in the cpp file:

    //A.cpp  
    namespace {  
      const std::string f1 = "filename1";  
      const std::string f2 = "filename2";  
      const std::string f3 = "filename3";  
    }
    
    //strings are used in this file  
    

Given these options, which one would you recommend and why?

9

There are 9 best solutions below

4
On BEST ANSWER

I'd place them in anonymous namespace in the CPP file. It makes them private to the implementation and at the same moment makes it visible to the non-member functions that are part of implementation (such as operator<<).

0
On

Just have the const strings at file scope in the implementation file, the anonymous namespace is not necessary to restrict their use to that class only.

C++ 003 Standard C.1.2 Clause 3: basic concepts

Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage

Note: The anonymous namespace does help reduce naming conflicts.

0
On

However you do it, one thing to be careful of: I wouldn't recommend using static std::string objects, instead use static char*. The reason for this is due to potential problems with order of initialisation. Say you have a static instance of a class whose constructor references the string A::f1. There is no guarantee that A::f1 has been constructed yet, and you'll get a crash, or worse, no crash but bogus data.

Tracking down order-of-initialisation bugs can be pretty nasty, and everything may look fine in one project, but then you might build another project using the same libraries, and the subtle differences in the link order will cause this bug to mysteriously appear.

0
On

If the strings are meant to be seen by users of the class, put them into the class. Otherwise, hide them in the implementation file's unnamed namespace.

0
On

If they are used only in a single file then there is no need to expose them to the outside world by including them in the header file.

If they are used and will always be used only in a single place then there's really no reason not to just write them as literals where they need to be used.

If they are used in multiple places in the cpp, I would go for the anonymous namespace.

Another option which you don't mention is to define them as static variables inside the cpp. this is somewhat equivalent to the anonymous namespace option and more C-like than C++.

0
On

Static members of the class.

If they are used in multiple places by the one class, it's usually easier to keep things organized - and to later find where you defined everything - if you keep them defined in the class that uses them. Defining them in-place makes them hard to locate and later modify. And I'd opt for the specific class over the anonymous namespace for cleaner class definition and use.

0
On

Of the three options, the only one you should really avoid is #1. Don't use magic cookies in your code. By putting the constants either in a namespace or a class, you make it easier to extend and maintain your code in the future.

If your constants are global in nature, then between 2 and 3, it matters little. What matters is that you choose one and stick with it. But if you have constants that apply to a particular class, then they should be a part of that class.

Personally, I'd use a namespace for most things.

0
On

I think the real issue is: Are the strings really only used internally when implementing the class, or are they used elsewhere.

To be really nit-picky, I would try to keep the interface of the class as clean as possible, so if the filename-strings should not be of any interest to the "outside" world. I would hide them internally in the .cpp-file only. And in that case I don't think I would bother with the namespace, but just keep things "static" (i.e. internal to the .cpp-file).

10
On

If only used in the class's .cpp file, there is no need to use a namespace of any sort, simply say:

const std::string f1 = "filename1";  
const std::string f2 = "filename2";  
const std::string f3 = "filename3";  

Overuse of namespaces seems to be the new thing - I can't personally see the attraction .