Identifier Scope

Every identifier has a scope that is determined by where it is declared. Identifier Scope in a program is the region(s) of the program within which the identifier can be used. Using a name outside of its scope is an error.

The same name may declared/used in different scopes. Ambiguities are resolved as follows:

  1. The name from the most local scope is used.
  2. If the name is not defined in the most local scope, the same name defined in the nearest enclosing scope will be used.
  3. If the name is not defined in any enclosing scope, then the compiler will report an error.

There are five possible scopes in C++.

  1. Block scope (local to a block of statements)
  2. Function scope (the entire extent of a function)[1]

    [1] Only labels have function scope.

  3. Class scope (the entire extent of a class, including its member functions)
  4. File scope (the entire extent of a source code file)
  5. Global scope (the entire extent of a program)

Because the compiler only deals with one source file at a time, only the Linker can tell the difference between global and file scope, as Example 20.3 shows.

Example 20.3. Global versus File scope

// In File 1:
int g1; // global
int g2; // global
static int g3; // keyword static limits g3 to file scope
(etc.)

// In File 2:
int g1; // linker error!
extern int g2; // okay, share variable space
static int g3; // okay: 2 different variable spaces
(etc.)

20.2.1. Default Scope of Identifiers: A Summary

Let's look at the five scopes in a bit more detail.

  1. Block scope. An identifier declared inside curly braces (excluding namespace blocks) { . . . } or in a function parameter list has block scope. Block scope extends from the declaration to the enclosing right brace.
  2. Function scope. Labels in C/C++ have their own scope. They are accessible before and after their declaration, for the whole function. C supports a very rarely used and often shunned goto statement that requires a label. The thing that makes its scope unique is that the label (the declaration) can appear after the first goto that uses it. Example 20.4 shows an example of its use. goto is seldom used by serious programmers but labels, because they exist, sometimes pop up in code and are used to solve various compatibility problems.[2]

    [2] Such as preventing the C++ compiler from choking on the signals: and slots: declarations.

    Avoid goto and labels in your code.

     
  3. Class scope. An identifier that is declared inside a class definition has class scope. Class scope is anywhere in the class definition[3] or in the bodies of member functions.[4]

    [3] Including inline function definitions above the declarations of referred members

    [4] Keeping in mind that the scope of non-static members excludes the bodies of static member functions

  4. File scope. This is basically the same as global scope, except that file scope variables are not exported to the linker. The keyword static hides an identifier from other source files and gives it file scope. File scope variables cannot be declared extern and accessed from another file.

    File scope variables, because they are not exported, do not pollute the global namespace. They are often used in C programs because C has no concept of private class members.

    File scope is available in C++ for backward compatibility with C, but we prefer to use namespaces or static class members instead.

     
  5. Global scope. An identifier whose declaration is not in between braces (round or curly) has global scope. The scope of such an identifier begins at the declaration and extends from there to the bottom of the source code file. extern declarations may be used to access global definitions in other source files.

    An identifier in a namespace is available from other scopes through the using keyword. It is also available globally through the use of the scope resolution :: operator. Namespace variables and static class members are accessible globally and have static storage, like global variables, except that they do not enlarge the global namespace. See Section 20.4 for more details.

Use of global scope for variables is unnecessary in C++. In general, only classes and namespaces should be defined in global scope. If you need a "global" variable, you can achieve something similar through the use of public static class member or a namespace member.

 

Example 20.4. src/goto/goto.cpp

[ . . . . ]
int look() {
 int i=0;
 for (i=0; i<10; ++i) {
 if (i == rand() % 20)
 goto found; <-- 1
 }
 return -1;
found: <-- 2
 return i;
}
[ . . . . ]
 

(1)It would be better to use break or continue.

(2)goto serves as a forward declaration to a label.

20.2.2. File Scope versus Block Scope and operator::

We have seen and used the scope resolution operator to extend the scope of a class or access its members with ClassName::. A similar syntax is used to access the individual symbols in a namespace with NamespaceName::. C++ also has a (unary) file scope resolution operator, ::, that provides access to global, namespace, or file scope objects from inside an enclosed scope. The following exercise deals with the use of this operator with various scopes.

Exercise: File Scope Versus Block Scope and Operator::

Determine the scope of each of the variables in Example 20.5. Then be the computer and predict the output of the program.

Example 20.5. src/early-examples/scopex.cpp

#include 
using namespace std;

long x = 17;
float y = 7.3; <-- 1
static int z = 11; <-- 2

class Thing {
 int m_Num; <-- 3
public:
 static int sm_Count; <-- 4
 Thing(int n = 0) : m_Num(n) {++sm_Count;}
 ~Thing() {--sm_Count;}
 int getNum() { return m_Num; }
};
int Thing::sm_Count = 0;
Thing t(11);

int fn(char c, int x) { <-- 5
 int z = 5; <-- 6
 double y = 6.933;
 {
 char y; <-- 7
 Thing z(4); <-- 8
 y = c + 3;
 ::y += 0.3; <-- 9
 cout << y << endl; <-- 10
 }
 cout << Thing::sm_Count
 << endl; <-- 11
 y /= 3.0; <-- 12
 ::z++; <-- 13
 cout << y << endl;
 return x + z;
}

int main() {
 int x, y = 10;
 char ch = 'B'; <-- 14
 x = fn(ch, y);
 cout << x << endl;
 cout << ::y << endl; <-- 15
 cout << ::x / 2 << endl;
 cout << ::z << endl;
}
 

(1)Scope: ________________

(2)Scope: ________________

(3)Scope: ________________

(4)Scope: ________________

(5)Scope: ________________

(6)Scope: ________________

(7)Scope: ________________

(8)Scope: ________________

(9)Scope: ________________

(10)Scope: ________________

(11)Scope: ________________

(12)Scope: ________________

(13)Scope: ________________

(14)Scope: ________________

(15)Scope: ________________


Part I: Introduction to C++ and Qt 4

C++ Introduction

Classes

Introduction to Qt

Lists

Functions

Inheritance and Polymorphism

Part II: Higher-Level Programming

Libraries

Introduction to Design Patterns

QObject

Generics and Containers

Qt GUI Widgets

Concurrency

Validation and Regular Expressions

Parsing XML

Meta Objects, Properties, and Reflective Programming

More Design Patterns

Models and Views

Qt SQL Classes

Part III: C++ Language Reference

Types and Expressions

Scope and Storage Class

Statements and Control Structures

Memory Access

Chapter Summary

Inheritance in Detail

Miscellaneous Topics

Part IV: Programming Assignments

MP3 Jukebox Assignments

Part V: Appendices

MP3 Jukebox Assignments

Bibliography

MP3 Jukebox Assignments



An Introduction to Design Patterns in C++ with Qt 4
An Introduction to Design Patterns in C++ with Qt 4
ISBN: 0131879057
EAN: 2147483647
Year: 2004
Pages: 268

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net