Let's assume that I have files a.cpp b.cpp and file c.h. Both of the cpp files include the c.h file. The header file contains a bunch of const int definitions and when I compile them I get no errors and yet I can access those const as if they were global variables. So the question, why don't I get any compilation errors if I have multiple const definitions as well as these const int's having global-like scope?
4 Answers
This is because a const
declaration at namespace scope implies internal linkage. An object with internal linkage is only available within the translation unit in which it is defined. So in a sense, the one const
object you have in c.h
is actually two different objects, one internal to a.cpp
and one internal to b.cpp
.
In other words,
const int x = ...;
is equivalent to
static const int x = ...;
while
int x;
is similar to
extern int x;
because non-const
declarations at namespace scope imply external linkage. (In this last case, they aren't actually equivalent. extern
, as well as explicitly specifying external linkage, produces a declaration, not a definition, of an object.)
Note that this is specific to C++. In C, const
doesn't change the implied linkage. The reason for this is that the C++ committee wanted you to be able to write
const int x = 5;
in a header. In C, that header included from multiple files would cause linker errors, because you'd be defining the same object multiple times.
From the current C++ standard...
7.1.1 Storage class specifiers
7) A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage.
3.5 Program and Linkage
2) When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
The preprocessor causes stuff defined in headers to be included in the current translation unit.