I'm relative new to C++ and have a question regarding private static member or "free nonmeber".
I can write my code like this:
// MyClass.h - Version 1
class MyClass
{
public:
MyClass();
~MyClass();
private:
static int iValue;
};
// MyClass.cpp
int MyClass::iValue = 123;
The other way without private member, with internal linking inside the cpp
// Version 2 - static
static int iValue = 123;
// or anonymouse namespace
namespace
{
int iValue2 = 123;
}
The only difference I can see is the "visibility" from outside of the class even though I can't use it.
If I want to use the iValue outside or in a derived class, I would declare the static member in Version 1 public or protected anyway or completely global above the class.
It is even more unclear for me with the keyword const.
class MyClass
{
private:
static const int iValue;
// (...)
}
I would always prefer to hide as many stuff from the outside as possible.
In short: Is there any reason why I should prefer Version 1 to Version 2?
Kind Regards
Nisi
Design decisions in this space need to balance a few things, which are good to understand so you can weigh the pros and cons each time such a choice is needed:
Anonymous namespaces or static non-members allow all later code in the translation unit full access.
Used in an implementation files (e.g. ".cc" / ".cpp"), they let you have some static data/functions - not extern
in the object's symbol table - which can't be accessed by code from other translation units.
Smaller symbol tables can sometimes reduce program linking and/or loading time.
This is generally deemed to have less encapsulation that a private member variable, as more than one class's code and friends can access/change the data (but definitions of class members may be spread across lots of translation units, and private data is more vulnerable to some types of "hacked" access such as client-provided template specialisations - nothing's ever clean-cut).
This reduces (re)compilation dependency (aka "physical dependency" in Lakosian terminology), meaning that you can change the data/functions without editing the header, and a recompile of just the translation unit lets the new data/behaviour be linked for incorporatation by however-many client objects/executables; that contrasts with edits to header files that tend to need recompilation and relinking of all the client code for incorporation. In enterprise-scale development that can be a big issue for changes in low-level libraries.
They're very rarely used in headers, because each translation unit that includes such a header would get an independent "copy" of the data/functions, and it's pretty rare for a program to want state stored per translation unit; that doesn't typically map cleanly onto logically meaningful divisions in the program data (e.g. per thread, per "user" at runtime), and even if a program could be structured so it appears useful it's generally better to manage multiple copies of data using object instances, keeping it uncoupled from translation units to preserve flexibility for later source code refactoring/restructuring.
They can't access any class's private/protected members, and there's a suggestion that they might unrelated to any specific class and potentially reusable, which - depending on how true that is - can aid or frustrate a developer's understanding when analysing the data usage or function behaviour/implementation.