double warming = 0.8; // new variable hides external one
cout << "Local warming = " << warming << " degrees.\n";
// Access global variable with the
// scope resolution operator
cout << "But global warming = " << ::warming;
cout << " degrees.\n";
}
Here is the output from the program:
Global warming is 0.3 degrees.
Updating global warming to 0.4 degrees.
Global warming is 0.4 degrees.
Local warming = 0.8 degrees.
But global warming = 0.4 degrees.
Global warming is 0.4 degrees.
Program Notes
The output of the program in Listings 9.5 and 9.6 illustrates that both main() and update() can access the external variable warming. Note that the change that update() makes to warming shows up in subsequent uses of the variable.
The definition for warming is in Listing 9.5:
double warming = 0.3; // warming defined
Listing 9.6 uses extern to make the warming variable available to the functions in that file:
extern double warming; // use warming from another file
As the comment indicates, this declaration says, “Use the warming variable defined externally elsewhere.”
In addition, the update() function re-declares the warming variable by using the keyword extern. This keyword means “Use the variable by this name previously defined externally.” Because that is what update() would do anyway if you omitted the entire declaration, this declaration is optional. It serves to document that the function is designed to use the external variable.
The local() function demonstrates that when you define a local variable that has the same name as a global variable, the local version hides the global version. The local() function, for example, uses the local definition of warming when it displays the value of warming.
C++ goes a step beyond C by offering the
Global Versus Local Variables
Now that you have a choice of using global or local variables, which should you use? At first, global variables have a seductive appeal—because all functions have access to a global variable, you don’t have to bother passing arguments. But this easy access has a heavy price: unreliable programs. Computing experience has shown that the better job your program does of isolating data from unnecessary access, the better job the program does in preserving the integrity of the data. Most often, you should use local variables and pass data to functions on a need-to-know basis rather than make data available indiscriminately by using global variables. As you will see, OOP takes this data isolation a step further.
Global variables do have their uses, however. For example, you might have a block of data that’s to be used by several functions, such as an array of month names or the atomic weights of the elements. The external storage class is particularly suited to representing constant data because you can use the keyword const to protect the data from change:
const char * const months[12] =
{
"January", "February", "March", "April", "May",
"June", "July", "August", "September", "October",
"November", "December"
};
In this example, the first const protects the strings from change, and the second const makes sure that each pointer in the array remains pointing to the same string to which it pointed initially.
Static Duration, Internal Linkage
Applying the static modifier to a file-scope variable gives it internal linkage. The difference between internal linkage and external linkage becomes meaningful in multifile programs. In that context, a variable with internal linkage is local to the file that contains it. But a regular external variable has external linkage, meaning that it can be used in different files, as the previous example showed.
What if you want to use the same name to denote different variables in different files? Can you just omit the extern?
// file1
int errors = 20; // external declaration
...
---------------------------------------------
// file2
int errors = 5; // ??known to file2 only??
void froobish()
{
cout << errors; // fails
...
No, this attempt fails because it violates the one definition rule. The file2 definition attempts to create an external variable, so the program winds up with two definitions of errors, which is an error.
But if a file declares a static external variable that has the same name as an ordinary external variable declared in another file, the static version is the one in scope for that file:
// file1
int errors = 20; // external declaration
...
---------------------------------------------