⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ref.html

📁 Visual C++ has been one of most effective tool for the large industrial applications. This book is t
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html>
<head>
    <title>References</title>
    <meta  name="description" content="References in C++">
    <meta name="keywords" content="reference, object, friend, passing, initializing">
    <link rel="stylesheet" href="rs.css" tppabs="http://www.relisoft.com/book/rs.css">
</head>

<body background="margin.gif" tppabs="http://www.relisoft.com/book/images/margin.gif" bgcolor="#FFFFDC">

<!-- Main Table -->
<table cellpadding="6">
    <tr>
    <td width="78">
	&nbsp;
    <td>
    
<h3>References</h3>
<p class=topics>References to objects, friends, passing by reference, initializing a reference.
<p>
So far we've been exploring the <i>has-a</i> and <i>is-a</i> types of relationships between objects. The third kind of relationship is <i><b>the has-access-to</b></i> relationship. The <i>has-access-to</i> relationship is not "destructive" like the others. Objects to which A has access are not destroyed when A is destroyed.
<p>
Of course, every object has access to all the global objects and to all objects within the encompassing scopes. However, in order to access these objects, the object in question (more precisely its class) has to have built-in knowledge of the actual <i>names</i> of these objects. For instance, class <var>World</var> knows about the existence of the globally accessible object <var>cout</var>. There's nothing wrong with having a few global objects whose names are known to lower level objects. They form the scenery of our program. They can be used to abstract some globally available services. However, the need for one object to access another object is so prevalent and dynamic that the above mechanism is not sufficient. The <i>has-access-to</i> relationship finds its expression in C++ in the form of references.
<p>
A reference refers to an object. It is like a new temporary name for an existing object--an alias. It can be used just like the original object; that is, the syntax for accessing a reference is the same as that for accessing an object. One can pass references, return references, even store them inside other objects. Whenever the contents of the object changes, all the references to this object show this change. Conversely, any reference can be used to modify the object it refers to (unless it's a <var>const</var> reference). 
<p>
We declare a reference variable by following the type name with an ampersand (actually, the ampersand <i>binds</i> with the name of the variable):
<!-- Code -->
<table width="100%" cellspacing=10><tr>
	<td class=codeTable>
<pre>Istack & stack;</pre>
</table>
<!-- End Code -->

<p>
One important thing about a reference is that, once it's created, and initialized to refer to a particular object, it will always refer to the same object. Assignment to a reference does not make it point to another object. It overwrites the object it refers to with the new value. For instance, consider this code
<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>int i = 5;
int j = 10;
int <b>&</b> iref = i;  // iref points to i
iref = j;</pre>
</table>
<!-- End Code -->
<p>
The execution of the last statement will result in changing the value of <var>i</var> from 5 to 10. It will not make <var>iref</var> point to <var>j</var>. Nothing can make <var>iref</var> point to anything other than <var>i</var>.
<p>
A reference cannot be created without being initialized. If a reference is stored within an object, it must be initialized in the preamble to the constructor of that object.
<p>
We'll use references in the definition and implementation of the stack sequencer. A sequencer is an object that is used to present some other object as a sequence of items; it returns the values stored in that object one by one. In order to retrieve values from the stack, the sequencer needs access to private data members of the stack. The stack may grant such access by making the sequencer its <var>friend</var>. All the stack's private data members are still invisible to the rest of the world, except for its new friend, the stack sequencer. Notice that friendship is a one way relationship: <var>StackSeq</var> can access private data of <var>IStack</var>, but not the other way around.
<p>
<!-- Sidebar -->
<table width="100%" border=0 cellpadding=5><tr>
<td width=10>
<td bgcolor="#cccccc" class=sidebar>

The combo <var>IStack</var> and <var>StackSeq</var> is an examples of a larger granularity structure, a pattern that unifies several data structures into one functional unit.

<td width=10>
</table>
<!-- End Sidebar -->

<tr>
<td class=margin valign=top>

<br>
<a href="javascript:if(confirm('http://www.relisoft.com/book/lang/ref/source/seq.zip  \n\nThis file was not retrieved by Teleport Pro, because it is linked too far away from its Starting Address. If you increase the in-domain depth setting for the Starting Address, this file will be queued for retrieval.  \n\nDo you want to open it from the server?'))window.location='http://www.relisoft.com/book/lang/ref/source/seq.zip'" tppabs="http://www.relisoft.com/book/lang/ref/source/seq.zip">
<img src="brace.gif" tppabs="http://www.relisoft.com/book/images/brace.gif" width=16 height=16 border=1 alt="Download!"><br>source</a>
<td>

<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>class <span class=method>IStack</span>
{
    friend class StackSeq; // give it access to private members
public:
    IStack (): _top (0) {}
    void Push (int i);
    int  Pop ();
private:
    int _arr [maxStack];
    int _top;
};</pre>
</table>
<!-- End Code -->

<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>class <span class=method>StackSeq</span>
{
public:
    StackSeq (IStack const & stack);
    bool AtEnd () const;    // are we done yet?
    void Advance (); // move to next item
    int GetNum ()const;   // retrieve current item
private:
    IStack const & _stack;  // reference to stack
    int     _iCur;   // current index into stack
};</pre>
</table>
<!-- End Code -->

<p>
The constructor of <var>StackSeq</var> is called with a reference to a <var>const IStack</var>. One of the data members is also a reference to a <var>const IStack</var>. A <var>const</var> reference cannot be used to change the object it refers to. For instance, since <var>Push</var> is not a <var>const</var> method, the compiler will not allow <var>StackSeq</var> to call <var>_stack.Push()</var>. It will also disallow any writes into the array, or any change to <var>_stack._top</var>. A reference to <var>const</var> can be initialized by any reference, but the converse is not true--a reference that is not <var>const</var> cannot be initialized by a reference to <var>const</var>. Hence we can pass any stack to the constructor of <var>StackSeq</var>. The compiler, in accordance with the declaration of the constructor, converts it to a reference to a <var>const IStack</var>. Then <var>_stack</var>, which is also a reference to a <var>const IStack</var>, may be initialized in the preamble to the constructor of the <var>StackSeq</var> (remember, references <i>must</i> be initialized in the preamble).
<p>
<img src="has-acc.gif" tppabs="http://www.relisoft.com/book/lang/ref/images/has-acc.gif" width=240 height=72 border=0 alt="Has-access-to">
<p class=caption>Figure 1 The graphical representation of the <i>has-access-to</i> relationship between objects.
<p>
Data member <var>_iCur</var> stores the state of the sequencer--an index into the array <var>_arr</var> inside the referenced stack. The sequencer being a friend of the class <var>IStack</var> has full knowledge of the stack's implementation.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre><span class=method>StackSeq::StackSeq</span> (IStack const & stack )
    : _iCur (0), _stack (stack) // init reference
{}</pre>
</table>
<!-- End Code -->

<p>
The implementation of the remaining methods is rather straightforward
<!-- Code -->
<table width="100%" cellspacing=10><tr>
    <td class=codeTable>
<pre>bool <span class=method>StackSeq::AtEnd</span> () const
{
    return _iCur == _stack._top;  // friend: can access _top
}

void <span class=method>StackSeq::Advance</span> ()
{
    assert (!AtEnd()); // not at end
    ++_iCur;
}

int <span class=method>StackSeq::GetNum</span> () const
{
    return _stack._arr [_iCur]; // friend: can access _arr
}</pre>
</table>
<!-- End Code -->


<p>
Notice that the dot syntax for accessing object's data members through a reference is the same as that of accessing the object directly. The variable <var>_stack</var> is a (read-only) alias for a stack object. Due to the sequencer's  <i>friend</i> status, <var>StackSeq</var> is accessing <var>IStack</var>'s private data members with impunity. 
<p>
New logical operators have been introduced in this program as well. The exclamation point logically negates the expression that follows it. <var>!AtEnd()</var> is true when the sequencer is not done and false when it's done. You read it as "not at end."
<p>
The double equal sign '==' is used for equality testing. The result is false if two quantities are different and true if they are equal. 


<tr>
<td class=margin valign=top>
<img src="bug.gif" tppabs="http://www.relisoft.com/book/images/bug.gif" width=25 height=25 border=0 alt=" ">

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -