📄 index.html
字号:
<!-- -*-html-*-
$Source: /usr/local/cvsroot/BigC++/20/index.html,v $
$Revision: 1.4 $
Big C++, chptr 20
editor: cols=80, tabstop=2
(c) 2005 John Wiley & Sons
Kurt Schmidt, kschmidt@cs.drexel.edu
NOTES
- 3 spaces are used for each indent in examples
REVISIONS:
12/19/03 - creation
1/10/04 - fixed spelling
$Log: index.html,v $
Revision 1.4 2004/03/29 05:49:16 kurt
Pared language, fixed tabs (spaces), added copyright to comments
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Copyright" content="2005 John Wiley & Sons">
<meta name="Author" content="Kurt Schmidt">
<script language="JavaScript" src="./config.js"></script>
<script language="JavaScript" src="./pageFormat.js"></script>
<script><!-- // Set title on page
title()
//--></script>
</head>
<body>
<h2><font color="#009999" size="+3">Chapter 20: Name Scope
Management</font></h2>
<font size="+1">
<script><!--
image( "cover.png" )
//--></script>
</font>
<hr><h2><font color="#009999" size="+2">Chapter Goals</font></h2>
<hr noshade size="4" color="#009999">
<font size="+1">
<ul>
<li>To understand how the management of names is tied to the management
of values</li>
<li>To understand the concepts of scope and visibility, and the various
scopes found in C++ programs</li>
<li>To learn how to use protected visibility to create an interface for
derived classes that is different from the public interface</li>
<li>To understand the use of alternative techniques for the management of
names, such as friends, nested classes, and private inheritance</li>
<li>To learn how to avoid ambiguity and duplicate names by using independent
name spaces</li>
</ul>
</font>
<hr><h2><font color="#009999">20.1 Encapsulation</font></h2>
<font size="+1">
<ul>
<li>Control complexity arising from name collisions</li>
<li>Hide or restrict access to members (sect. 6.3):
<blockquote>
<pre>class Product
{
public:
Product();
void read();
bool is_better_than(Product b) const;
void print() const;
<font color="#009999">private:
string name;
double price;
int score;</font>
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">20.1 Encapsulation (cont.)</font></h2>
<font size="+1">
<ul>
<li>Encapsulation restricts access to <i>names</i></li>
<li>Same as restricting access to values</li>
<li>E.g., P1 creates a stack class that P2 will use (prev. chapter):
<ul>
<li>Encapsulation limits the information P2 must know</li>
<li>Data fields are inaccessible to P2</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">20.2 Name Scopes</font></h2>
<font size="+1">
<dl>
<dt>Scope</dt>
<dd>The part of a program where a name is visible and has meaning (sect.
5.9)</dd>
</dl>
<p>Scopes we have seen:</p>
<ul>
<dl>
<dt>Block Scope</dt>
<dd>Any block delimited by curly braces (<tt>{}</tt>). Name is destroyed
after the closing curly brace</dd>
<dt>Local Scope</dt>
<dd>Special case of block scope. A function's local variables
and formal parameters have meaning only inside that function</dd>
</dl>
</ul>
</font>
<hr><h2><font color="#009999">20.2 Name Scopes (cont.)</font></h2>
<font size="+1">
<p>Scopes we have seen (cont.):</p>
<ul>
<dl>
<dt>Class Scope</dt>
<dd><tt>private</tt> members of a class only have meaning to other members
(and friends) of that class</dd>
<dt>Global Scope</dt>
<dd>Identifiers declared outside functions and classes</dd>
<dd>From declaration until the end of file</dd>
<dd>Visible in other files by declaring it as <tt>extern</tt></dd>
<dt>File Scope</dt>
<dd>A <tt>static</tt> <u>global</u> - "local" to file</dd>
</dl>
</ul>
</font>
<hr><h2><font color="#009999">20.2 Name Scopes (cont.)</font></h2>
<font size="+1">
<p>Scopes may nest</p>
<blockquote>
<pre>int count = 0; <font color="#0000cc">// Create a global variable</font>
. . .
int count_items()
{
int orig_count = count; <font color="#0000cc">// holds value in global variable</font>
int count = 0; <font color="#0000cc">// A different variable named count</font>
for (...)
count++; <font color="#0000cc">// Increment the local variable</font>
return count + orig_count;
}
<font color="#0000cc">// Local count and orig_count are no longer available,</font></pre>
</blockquote>
</font>
<hr><h2><font color="#009999">20.2.1 Shadows and Qualification</font></h2>
<font size="+1">
<ul>
<li>A name can hide (or block) a name from an outer scope</li>
<li>This name <i>shadows</i> the previous definition</li>
<li>Name resumes its previous meaning when inner scope exits</li>
</ul>
</font>
<hr><h2><font color="#009999">20.2.1 Shadows and Qualification</font></h2>
<font size="+1">
<p>To access (some) hidden names:</p>
<ul>
<li>Use <tt>this</tt> to get to hidden attributes (next slide)</li>
<li>Use the unary scope <tt>::</tt> to access globals (next slide)</li>
<li>Binary scope to get to another class' hidden names:
<blockquote>
<pre>int TravelClock::get_hours() const
{
int h = Clock::get_hours();
<font color="#0000cc">// Qualify which get_hours is intended</font>
. . .
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">20.2.1 Example</font></h2>
<font size="+1">
<p>Perverse example:</p>
<blockquote>
<pre><font color="#0000cc">// DONT WRITE CODE SUCH AS THIS!</font>
double balance; <font color="#0000cc">// balance has global scope</font>
class BankAccount
{
public:
BankAccount(double balance);
<font color="#0000cc">// Parameter variable balance has local scope</font>
private:
double balance; <font color="#0000cc">// Data field balance has class scope</font>
};</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">20.2.1 Example (cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>BankAccount::BankAccount(double balance)
{
this->balance = balance;
<font color="#0000cc">// Assign data field balance using parameter value</font>
::balance = balance;
<font color="#0000cc">// Assign global variable using parameter value</font>
}</pre>
</blockquote>
<ul>
<li><tt>balance</tt> member shadows the global</li>
<li>C'tor's parameter shadows both the attribute and the global</li>
<li>Don't need <tt>orig_count</tt></li>
</ul>
</font>
<hr><h2><font color="#009999">Advanced Topic 20.1</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<p><font color="#009999">Overriding, Shadowing, and Scopes</font></p>
<ul>
<li>Overloading an inherited member function hides that function:
</li>
</ul>
<blockquote>
<pre>class Employee
{ . . .
virtual void set_salary(int new_salary);
};
class Manager : public Employee
{ . . .
virtual void set_salary(int new_salary, int yearly_bonus);
};
Manager m;
m.set_salary(45000); <font color="#ff0000">// Error - requires 2 args</font></pre>
</blockquote>
</font>
<hr><h2><font color="#009999">Advanced Topic 20.1 (cont.)</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<ul>
<li>To fix:
<ul>
<li>Override the function in the derived class</li>
<li>call the base class' method explicitly</li>
</ul>
</li>
</ul>
<blockquote>
<pre>class Manager : public Employee
{
. . .
virtual void set_salary(int new_salary);
void set_salary(int new_salary, int yearly_bonus);
};
void Manager::set_salary(int new_salary)
{
Employee::set_salary(new_salary); <font color="#0000cc">// Invoke the base class function</font>
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">20.3 Protected Scope</font></h2>
<font size="+1">
<ul>
<li>Derived class inherits <tt>private</tt> members, but can not access
them</li>
<li><tt>protected</tt> indicates members that only derived classes can
access</li>
<li>Example: <tt>Chart</tt> stores data, derived classes <tt>PieChart</tt>,
<tt>BarChart</tt>, etc. each display data in a different fashion:</li>
</ul>
</font>
<hr><h2><font color="#009999">20.3 Protected Scope (cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>class Chart
{
public:
virtual void draw() const;
. . .
protected:
vector<double> data;
};
class PieChart : public Chart
{
public:
virtual void draw() const;
. . .
};</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">20.3 Protected Scope (cont.)</font></h2>
<font size="+1">
<table border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1"><font color="#009999">Syntax 20.1:
Protected Members</font>
<pre>class <i>ClassName</i>
{
. . .
protected:
<i>member functions and data fields</i>
};</pre>
<table border="0" cellpadding="4">
<tr>
<td valign="top"><font size="+1" color="#009999">Purpose:</font></td>
<td><font size="+1">Declare member functions and data fields that are
visible to derived classes.</font></td>
</tr>
</table>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">20.3 Protected Scope (cont.)</font></h2>
<font size="+1">
<table width='100%' border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1"><font color="#009999">
Syntax 20.1 (cont.)
<table border="0" cellpadding="4">
<tr>
<td valign="top"><font size="+1" color="#009999">
Example:</font></td>
<td><font size="+1">
<pre>class Chart
{
. . .
protected:
vector<double> data;
double value_at(int index) const;
};</pre>
</font>
</td>
</tr>
</table>
</font>
</td>
</tr>
</table>
<ul>
<li>Classes now have three interfaces</li>
<li><font color="#009999">Tip:</font> Use protected methods to access
private data</li>
</ul>
</font>
<hr><h2><font color="#009999">20.4 Friends</font></h2>
<font size="+1">
<ul>
<li>Grants access to non-public members to another function or non-derived
class</li>
<li>Declare other entity as a <i>friend</i> in class definition</li>
<li>Each friend must be explicitly named</li>
<li>Granting friendship to a class grants access to all of its member
functions</li>
<li>Still dangerous, but more precise mechanism</li>
</ul>
</font>
<hr><h2><font color="#009999">20.4 Friends (cont.)</font></h2>
<font size="+1">
<ul>
<li>Refer to section 16.2.1:
<blockquote>
<pre>class Node
{
public:
Node(string s);
private:
string data;
Node* previous;
Node* next;
<font color="#009999">friend class List;
friend class Iterator;</font>
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">20.4 Friends (cont.)</font></h2>
<font size="+1">
<ul>
<ul>
<li>Only <tt>List</tt> and <tt>Iterator</tt> are allowed to view and
modify data fields of <tt>Node</tt></li>
</ul>
<li>Friendship is granted, not taken</li>
<li>Friend functions are <i>not</i> member functions</li>
<li>Access modifier is irrelevant</li>
<li>Friendship is <i>not</i> symmetric</li>
</ul>
</font>
<hr><h2><font color="#009999">20.4 Friend - syntax</font></h2>
<font size="+1">
<table border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1"><font color="#009999">Syntax 20.2:
Friends</font>
<pre>class <i>ClassName</i>
{
. . .
<font color="#009999">friend class <i>ClassName</i>;
friend <i>return_type function_name(parameter list)</i>;</font>
}</pre>
<table border="0" cellpadding="4">
<tr>
<td valign="top"><font size="+1" color="#009999">Purpose:</font></td>
<td><font size="+1">Allow other classes and functions access to
private features of a class.</font></td>
</tr>
</table>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">20.4 Friend - syntax (cont.)</font></h2>
<font size="+1">
<table width='100%' border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1">
<table border="0" cellpadding="4">
<tr>
<td valign="top"><font size="+1" color="#009999">
Example:</font></td>
<td valign='top'><font size="+1">
<pre>class Node
{
public:
Node(string s);
private:
string data;
Node* previous;
Node* next;
<font color="#009999">friend class List;
friend class Iterator;</font>
};
class Employee
{
. . .
<font color="#009999">friend ostream& operator<<(ostream& out,
const Employee& e)</font>
};</pre>
</font>
</td>
</tr>
</table>
</font>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">20.4 Friends & Streams</font></h2>
<font size="+1">
<p>Example: <tt>stream</tt> operators:</p>
<blockquote>
<pre>class Employee
{
public:
Employee(string employee_name, double initial_salary);
. . .
private:
string name;
double salary;
<font color="#009999">friend ostream& operator<<(ostream& out, const Employee& e);</font>
};</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">20.4 Friends & Streams (cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>ostream& operator<<(ostream& out, const Employee& e)
{
out << "Employee: " << e.name;
return out;
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">20.5 Nested Classes</font></h2>
<font size="+1">
<ul>
<li>Compare our <tt>Iterator</tt> (chptr. 16):
<blockquote><tt>
Iterator pos = staff.begin();
</tt></blockquote>
</li>
<li>to the STL <tt>iterator</tt>:
<blockquote><tt>
list<string>::iterator pos = staff.begin();
</tt></blockquote>
</li>
<li><tt>iterator</tt> is <i>nested</i> inside the <tt>list</tt>
class</li>
<li>Allows other containers to define their own iterators with different
behaviors</li>
</ul>
</font>
<hr><h2><font color="#009999">20.5 Nested Classes (cont.)</font></h2>
<font size="+1">
<ul>
<li>Have the same interfaces</li>
<li>Share names, but not in the same namespace</li>
<li>Expressed with a qualified name:
<blockquote><tt>
vector<double>::iterator p = a.begin();<br>
list<string>::iterator q = b.begin();
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">20.5 Nested Classes - syntax</font></h2>
<font size="+1">
<table width='100%' border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1"><font color="#009999">Syntax 20.3:
Nested Class Declaration</font>
<pre>class <i>OuterClassName</i>
{
. . .
class <i>NestedClassName</i>;
. . .
};</pre>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">20.5 Nested Classes - syntax (cont.)</font></h2>
<font size="+1">
<table border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1"><font color="#009999">Syntax 20.3:
Nested Class Declaration (cont.)</font>
<table border="0" cellpadding="4">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -