C++ Scope Rules

Read time: 19 minutes (4874 words)

When we build C++ programs, we need to create containers for our data. We also create functions and other things that have names. It is important that you be able to figure out exactly where in your code you can use the names you define. The rules for all of this are called “Scope Rules”.

Note

This has nothing to do with mouthwash!

Glass Walls

To understand these rules, lets build some walls around chunks of code. These walls will be made of glass, actually, they will be made of one-way mirrored glass. From inside the walls you can see out. From outside, you cannot see in! Got that! It will help in understanding the rules.

There is one more big rule in C++. You can only look upward, toward the top of your code to figure out what a name means. You can never look downward, toward the bottom. The compiler reads your code top to bottom, and will not wait until later to figure out what a name is all about when you try to use it.

With this background, we can now explain the scope rules!

C++ Scope Regions

C++ defines several different regions of code inside of which you can create names. Each region is surrounded by our glass walls. We will not look at all of these regions in this class, but we will look at the most important ones:

  • File Scope - outside of any other enclosing region.
  • Function Scope - encloses the entire function, including the parameter list on the function declaration.
  • Class Scope - encloses a class definition (we will get to these).
  • Block Scope - surrounds a block of code surrounded by curly braces
  • Namespace Scope - used to avoid collisions in names set up by different programmers

File Scope

Any name declared in a file, outside of any other enclosing region has “file scope”. That name can be used by any code in the file, from the time it is declared, until the end of the file. These names are “global” in the sense that they can be used anywhere with in the file. Note that they cannot be used in other files, though!

Function Scope

When you declare a function in your code, you can create variables inside the function. Those variables are invisible to the outside world. They are called “local variables”. If you use a name inside the function that is not defined inside the function, it must have been defined in the file above this function (in the global file scope) to be used here. If you declare a new variable with the same name as an existing global variable but inside the function, the outer global variable will not be visible inside your function, the new local variable will be used instead!

It is important to remember that the names you set up (and their declared types) on the parameter list of a function are also local variables in the function. You are free to use then as you wish. Be careful if those variables were declared as “reference parameters though! You are using variables from some other scope!

Class Scope

We have not studied this concept yet, but we will soon. The class sets up another kind of container with a glass wall around it. We will discuss this scope when we study classes and objects.

Block Scope

When something is surrounded by curly brackets, you are defining something we call a “block”. You can create variables inside this region, and they will only exist inside that block. You can use then as you wish in the code in the block, but those variables will be destroyed when you exit the block.

Note that the C++ “for loop” allows you to declare a new loop counter variable, and that scope of that variable is the block that makes up the loop body.

Namespace Scope

C++ was designed to support big programs, especially those developed by many programmers. It is almost certain that some two programmers will build things witht he same names, but in different parts of the program. When we try to hook these parts together, we get “name collisions” and the compiler cannot figure out what name to use in any given situation.

The C++ designers get around this problem by adding a new glass wall around a chunk of code. We call that new chunk a “namespace” and the name you give this space is arbitrary.

You have already run into one namespace, the std namespace.

Normally, to access a name protected by a namespace, you would do this:

std::cout << "hello" << std::endl;

Both names cout and endl were defined inside the std namespace. If we want to get rid of that extra notation, because we are going to reference names that are inside that namespace wall, we can add this line:

using namespace std;

Then we are free to leave off the extra markers.

Warning

Modern C++ programmers do not want you to ue a “using namespace” line in your code. DOing so adds a ton of new names which may not be used for your own purposes. Use the funny “std::cout”” style and access only the specific names from a namespace that you need.

You can use more than one namespace in a program, and you reference names from each in the same way, using the right namespace name as a prefix. If you add multiple “using namespace” lines, you are responsible for making sure there are no name collisions!