12.3. Class Scope
Every class defines its own new scope and a unique type. The declarations of the class members within the class body introduce the member names into the scope of their class. Two different classes have two different class scopes.

class First {
public:
int memi;
double memd;
};
class Second {
public:
int memi;
double memd;
};
First obj1;
Second obj2 = obj1; // error: obj1 and obj2 have different types
Using a Class Member
Outside the class scope, members may be accessed only through an object or a pointer using member access operators dot or arrow, respectively. The left-hand operand to these operators is a class object or a pointer to a class object, respectively. The member name that follows the operator must be declared in the scope of the associated class:
Some members are accessed using the member access operators; others are accessed directly from the class using the scope operator, (::). Ordinary data or function members must be accessed through an object. Members that define types, such as Screen::index, are accessed using the scope operator.
Class obj; // Class is some class type
Class *ptr = &obj;
// member is a data member of that class
ptr->member; // fetches member from the object to which ptr points
obj.member; // fetches member from the object named obj
// memfcn is a function member of that class
ptr->memfcn(); // runs memfcn on the object to which ptr points
obj.memfcn(); // runs memfcn on the object named obj
Scope and Member Definitions
Member definitions behave as if they are in the scope of the class, even if the member is defined outside the class body. Recall that member definitions that appear outside the class body must indicate the class in which the member appears:
Here we use the fully qualified name Sales_item::avg_price to indicate that the definition is for the avg_price member in the scope of the Sales_item class. Once the fully qualified name of the member is seen, the definition is known to be in class scope. Because the definition is in class scope, we can refer to revenue and units_sold without having to write this->revenue or this->units_sold.
double Sales_item::avg_price() const
{
if (units_sold)
return revenue/units_sold;
else
return 0;
}
Parameter Lists and Function Bodies Are in Class Scope
In a member function defined outside the class, the parameter list and member-function body both appear after the member name. These are defined inside the class scope and so may refer to other class members without qualificationfor example, the definition of the two-parameter version of get in class Screen:
This function uses the type name index defined inside Screen to name the types of its parameters. Because the parameter list is inside the scope of class Screen, there is no need to specify that we want Screen::index. It is implicit that the one we want is the one defined in the current class scope. Similarly, the uses of index, width, and contents all refer to names declared inside class Screen.
char Screen::get(index r, index c) const
{
index row = r * width; // compute the row location
return contents[row + c]; // offset by c to fetch specified character
}
Function Return Types Aren't Always in Class Scope
In contrast to the parameter types, the return type appears before the member name. If the function is defined outside the class body, then the name used for the return type is outside the class scope. If the return type uses a type defined by the class, it must use the fully qualified name. For example, consider the get_cursor function:
The return type of this function is index, which is a type name defined inside the Screen class. If we define get_cursor outside the class body, the code is not in the class scope until the function name has been processed. When the return type is seen, its name is used outside of the class scope. We must use the fully qualified type name, Screen::index to specify that we want the name index that is defined inside class Screen.
class Screen {
public:
typedef std::string::size_type index;
index get_cursor() const;
};
inline Screen::index Screen::get_cursor() const
{
return cursor;
}
Exercises Section 12.3
Exercise 12.15:List the portions of program text that are in class scope.Exercise 12.16:What would happen if we defined get_cursor as follows:
index Screen::get_cursor() const
{
return cursor;
}
12.3.1. Name Lookup in Class Scope
In the programs we've written so far, name lookup (the process of finding which declaration is matched to a given use of a name) has been relatively straightforward:
- First, look for a declaration of the name in the block in which the name was used. Only names declared before the use are considered.If the name isn't found, the enclosing scope(s) are searched.

- First, the member declarations are compiled.Only after all the class members have been seen are the definitions themselves compiled.
Name Lookup for Class Member Declarations
Names used in the declarations of a class member are resolved as follows:
- The declarations of the class members that appear before the use of the name are considered.If the lookup in step 1 is not successful, the declarations that appear in the scope in which the class is defined, and that appear before the class definition itself, are considered.
When processing the declaration of the balance function, the compiler first looks for a declaration of Money in the scope of the class Account. The compiler considers only declarations that appear before the use of Money. Because no member declaration is found, the compiler then looks for a declaration of Money in global scope. Only the declarations located before the definition of the class Account are considered. The declaration for the global typedef Money is found and is used for the return type of the function balance and the data member bal.
typedef double Money;
class Account {
public:
Money balance() { return bal; }
private:
Money bal;
// ...
};

typedef double Money;
class Account {
public:
Money balance() { return bal; } // uses global definition of Money
private:
// error: cannot change meaning of Money
typedef long double Money;
Money bal;
// ...
};
Name Lookup in Class Member Definitions
A name used in the body of a member function is resolved as follows:
- Declarations in the member-function local scopes are considered first.If the a declaration for the name is not found in the member function, the declarations for all the class members are considered.If a declaration for the name is not found in the class, the declarations that appear in scope before the member function definition are considered.
Class Members Follow Normal Block-Scope Name Lookup

When looking for a declaration for the name height used in the definition of dummy_fcn, the compiler first looks in the local scope of that function. A function parameter is declared in the local scope of its function. The name height used in the body of dummy_fcn refers to this parameter declaration.In this case, the height parameter hides the member named height.
// Note: This code is for illustration purposes only and reflects bad practice
// It is a bad idea to use the same name for a parameter and a member
int height;
class Screen {
public:
void dummy_fcn(index height) {
cursor = width * height; // which height? The parameter
}
private:
index cursor;
index height, width;
};

// bad practice: Names local to member functions shouldn't hide member names
void dummy_fcn(index height) {
cursor = width * this->height; // member height
// alternative way to indicate the member
cursor = width * Screen::height; // member height
}
After Function Scope, Look in Class Scope
If we wanted to use the member named height, a much better way to do so would be to give the parameter a different name:
Now when the compiler looks for the name height, it will not find that name in the function. The compiler next looks in the Screen class. Because height is used inside a member function, the compiler looks at all the member declarations. Even though the declaration of height appears after its use inside dummy_fcn, the compiler resolves this use to the data member named height.
// good practice: Don't use member name for a parameter or other local variable
void dummy_fcn(index ht) {
cursor = width * height; // member height
}
After Class Scope, Look in the Surrounding Scope
If the compiler doesn't find the name in function or class scope, it looks for the name in the surrounding scope. In our example, declarations in global scope that appear before the definition of the Screen include a global object named height. However, that object is hidden.

// bad practice: Don't hide names that are needed from surrounding scopes
void dummy_fcn(index height) {
cursor = width * ::height;// which height? The global one
}
Names Are Resolved Where They Appear within the File
When a member is defined outside the class definition, the third step of name lookup not only considers the declarations in global scope that appear before the definition of class Screen, but also considers the global scope declarations that appear before the member function definitionfor example:
Notice that the declaration of the global function verify is not visible before the definition of the class Screen. However, the third step of name lookup considers the surrounding scope declarations that appear before the member definition, and the declaration for the global function verify is found.
class Screen {
public:
// ...
void setHeight(index);
private:
index height;
};
Screen::index verify(Screen::index);
void Screen::setHeight(index var) {
// var: refers to the parameter
// height: refers to the class member
// verify: refers to the global function
height = verify(var);
}
Exercises Section 12.3.1
Exercise 12.17:What would happen if we put the typedef in the Screen class as the last line in the class?Exercise 12.18:Explain the following code. Indicate which definition of Type or initVal is used for each use of those names. If there are any errors, say how you would fix the program.
The definition of the member function setVal is in error. Apply the necessary changes so that the class Exercise uses the global typedef Type and the global function initVal.
typedef string Type;
Type initVal();
class Exercise {
public:
// ...
typedef double Type;
Type setVal(Type);
Type initVal();
private:
int val;
};
Type Exercise::setVal(Type parm) {
val = parm + initVal();
}