1. The easiest constants in classes are made by using enums:
class SomeClass
{
enum { SIZE= 7 };
std::vector<int> intVector;
public:
SomeClass(): intVector(SIZE) {}
};
Two problems with this. The first is that it can only be used
for integral constants; it doesn't work for floating point (the
actual example) or user defined types. The second is that even
for integral constants, the type is wrong, which has
repercusions with regards to function overload resolution and
templates.
The usual solution here is to declare a static const member,
e.g.:
class SomeClass
{
public:
static std::size_t const size = 7 ;
static double const pi ;
// ...
} ;
In all cases, you must define the variable in a single source
file. In the case of an integral constant, you can put the
initializer (the value) either in the declaration in the class,
or in the definition. For all other types, the initializer can
only go in the definition.
2. Regarding global constants and the header file you mentioned, in
simple words:
You can #include the header file with the global constant only in one
"implementation" file (e.g. .cpp) and to the rest implementation files
(e.g. .cpp), you can add the declaration:
In that case, you must also declare the definition extern:
extern double const PI = 3.14 ;
Otherwise, it doesn't have external linkage.
It's more frequent to simply write:
double const PI = 3.14 ;
in the header. Be aware, however, that this means that &PI may
not always be the same thing. (Not usually a problem for the
standard arithmetic types, but it easily could be a problem with
user defined types.)
==> In general avoid objects in the global namespace.
Except maybe for some global constants
.
3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).
file1.cpp:
E.g. pi.h:
namespace SomeNamespace
{
const double PI = 3.14;
}
What should be preferred instead of constants in the global
namespace:
Constants (consts/enums) in anonymous namespaces (= local file
scope only), and constants (consts/enums) in named namespaces.
I don't think that that's a good general policy. You don't want
to have an anonymous namespace in a header, since it's generally
a very good way to end up with undefined behavior.
Regarding classes, you can either use static constants or
(usually better) enums.
Enums were what was used before the rules were changed to allow
the initializer in the declaration. The rule was changed
because using enums created too many problems due to the type
being wrong.