3
votes

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

4 Answers

5
votes

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.

2
votes

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.

0
votes

When you do so, you create a separate const variable in each object file for every constant in the header. It's not a problem, since they are const.

0
votes

Real reason: because #define is evil and needs to die.

Some usages of #define can be replaced with inline functions. Some - with const variable declarations. Since #define tends to be in header files, replacing those with consts in place better work. Thus, the "consts are static by default" rule.