2.2 Scope

A scope is a region of source code that contains declarations. Every declaration adds a name to a scope, and every use of a name requires the compiler to identify which scope contains that name's declaration. Sometimes you tell the compiler exactly which scope contains the name, and at other times the compiler determines the scope. Once the compiler knows the scope, it can look up the name to learn what the name is (object, function, class, etc.) and how the name can be used. Thus, you can think of a scope as a dictionary of names mapped to declarations.

A scope can be named or unnamed. Classes and namespaces (see Section 2.7 later in this chapter) define named scopes. Statement blocks, function bodies, and unnamed namespaces define unnamed scopes. You can qualify a name with a scope name to tell the compiler where to look up the qualified name, but you cannot qualify names from unnamed scopes. In a typical program, most names are unqualified, so the compiler must determine which scope declares the name. (See Section 2.3 later in this chapter.)

Scopes can be nested, and names in inner scopes can hide names that are declared in outer scopes. Example 2-2 illustrates abuses of the simple scope rules: the body of the for loop is a scope, in which the variable x is declared as an int; the if statement creates a nested scope, in which another declaration of x hides the outer x. The reference to x at the end of main is invalid: no x is in scope at that point.

Example 2-2. Names in inner scopes can hide names in outer scopes
#include <iostream>

#include <ostream>



int main(  )

{

  for (int i = 0; i < 100; ++i)

  {

    int x = 42;

    if (x < i)

    {

      double x = 3.14;

      std::cout << x; // Prints 3.14

    }

    std::cout << x;   // Prints 42

  }

  std::cout << x;     // Error: no x declared in this scope

}

At the same scope level, you cannot have multiple declarations for the same name, unless every declaration of that name is for an overloaded function or function template, or if the declarations are identical typedef declarations.

Example 2-2 shows that a name can be hidden by a different declaration in an inner scope level. Also, a class name or enumeration type name can be hidden by an object, function, or enumerator at the same scope level. For example:

enum x { a, b, c };

const int x = 42;   // OK: hides enum x

const int a = 10;   // Error: int cannot hide enumerator a

{

  const int a = 10; // OK: inner scope can hide outer a

}

Different entities (functions, statements, classes, namespaces, etc.) establish scope in different ways. The description of each entity (in this and subsequent chapters) includes scoping rules. The general rule of thumb is that curly braces delimit a scope region. The outermost scope region is outside of all the curly braces and is called the global scope. (See Section 2.7 later in this chapter.)