I'm running a simple program similar to what I found here. It's meant to reduce code bloat when including constants in multiple files. It does this by using const global variables within a namespace with their respective extern
forward declarations.
globals.h
#ifndef GLOBALS_H_
#define GLOBALS_H_
namespace Constants
{
// forward declarations only
extern const double pi;
extern const double avogadro;
extern const double my_gravity;
}
#endif
globals.cpp
namespace Constants
{
// actual global variables
extern const double pi(3.14159);
extern const double avogadro(6.0221413e23);
extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
}
source.cpp
#include <iostream>
#include <limits>
#include "globals.h"
int main()
{
double value_of_pi = Constants::pi;
std::cout << value_of_pi;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
return 0;
}
I assume that Constants::pi gets the value pi contained in the globals.cpp Constants namespace, and is able to do so because it has access to the namespace itself from the included globals.h. What I don't understand is why the const global definitions/initializations in globals.cpp need the extern
keyword? I tried removing the extern
keywords in globals.cpp thinking that it wasn't needed, but my program won't run without them. I thought extern
was only used for forward declarations? Why are they needed for the const global definitions/initializations? Has it something to do with the namespace they are defined in?
You don't need to make the namespace extern, you need to make the variables extern. The fact that they are in a namespace is irrelevant.
the extern keyword is used to extend the visibility of variables/functions. Since functions are visible throughout the program by default, the use of extern is not needed in function declarations or definitions. Its use is implicit. When extern is used with a variable, it's only declared, not defined.
“extern” keyword is used to extend the visibility of function or variable. By default the functions are visible throughout the program, there is no need to declare or define extern functions. It just increase the redundancy. Variables with “extern” keyword are only declared not defined.
An external variable can be accessed by all the functions in all the modules of a program. It is a global variable. For a function to be able to use the variable, a declaration or the definition of the external variable must lie before the function definition in the source code.
It's meant to reduce code bloat when including constants in multiple files
I would suggest not to focus on this kind of optimizations unless it becomes really necessary, and rather choose the simplest design: define those constants directly in the header file and include that header file from all translation units (".cpp files") that need to access those constants. Since those objects are const
, they will have internal linkage and the linker won't be screaming at you due to violations of the One Definition Rule.
I tried removing the extern keywords in globals.cpp thinking that it wasn't needed, but my program won't run without them
That's because namespace-scope const
objects with static storage duration (like your pi
variable) have internal linkage unless you explicitly define them as extern
.
I thought extern was only used for forward declarations?
extern
is used to declare a variable that is defined in another translation unit (".cpp file"). If the object is const
, the translation unit that defines it needs to explicitly mark it as extern
in order for it to have external linkage and be visible from other translation units (this wouldn't be necessary if the object were not const
).
Has it something to do with the namespace they are defined in?
No, this is the rule for all namespace-level const
objects with static storage duration, and it is specified in paragraph [basic.link]/3 of the C++ Standard:
A name having namespace scope (3.3.6) has internal linkage if it is the name of
(3.1) [...] — a variable, function or function template that is explicitly declared static; or,
(3.2) — a variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or
(3.3) — a data member of an anonymous union.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With