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

📄 ch09.htm

📁 Visual C++ 的学习资料 Visual C++ 的学习资料
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<TT>    cout &lt;&lt; &quot;pVar's value is &quot; &lt;&lt; pVar &lt;&lt; &quot;.&quot; &lt;&lt; endl;</TT>
<TT>    cout &lt;&lt; &quot;*pVar's value is &quot; &lt;&lt; *pVar &lt;&lt; &quot;.&quot; &lt;&lt; endl;</TT>

<TT>    return 0;</TT>
<TT>}</TT>
</FONT></PRE>
<P>It's important to remember that the pointer does not contain a variable's value,
only its address. The indirection operator enables you to refer to the value stored
at the address instead of to the address itself.</P>
<P>As shown in Listing 9.4, a pointer variable is declared using the indirection
operator, like this:</P>
<PRE><FONT COLOR="#0066FF"><TT>int*     pVar;  // declare a pointer to int</TT>
</FONT></PRE>


<BLOCKQUOTE>
	<P>
<HR>
<B> </B><FONT COLOR="#000077"><B>CAUTION:</B></FONT><B> </B>If you are in the habit
	of declaring several variables on one line, look out for pointer declarations. The
	indirection operator applies only to the object to its immediate right, not to the
	whole line. The declaration</P>
	<PRE><FONT COLOR="#0066FF"><TT>int* pFoo, pBar;</TT></FONT></PRE>

</BLOCKQUOTE>

<PRE><FONT COLOR="#0066FF"><TT></TT></FONT></PRE>


<BLOCKQUOTE>
	<P>declares and defines two variables: a pointer to an <TT>int</TT> named <TT>pFoo</TT>,
	and an <TT>int</TT> named <TT>pBar</TT>. The <TT>pBar</TT> variable is not a pointer.
	If you insist on declaring more than one pointer per line, use this style:

</BLOCKQUOTE>

<PRE></PRE>


<BLOCKQUOTE>
	<P><FONT COLOR="#0066FF"><TT>int *pFoo, *pBar;</TT></FONT> 
<HR>


</BLOCKQUOTE>

<PRE></PRE>
<P>Pointers are useful when you must change a parameter inside a function. Because
parameters are always passed by value, the only way to change the value of a parameter
inside a function is to send the address of the variable to the function, as Listing
9.5 does.
<H4><FONT COLOR="#000077">TYPE: Listing 9.5. Using a pointer and a function to change
a variable's value.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>#include &lt;iostream&gt;</TT>
<TT>using namespace std;</TT>
<TT>void IncrementVar( int* pVar );</TT>

<TT>int main()</TT>
<TT>{</TT>
<TT>    int  nVar = 0;</TT>

<TT>    cout &lt;&lt; &quot;The value of nVar is now &quot; &lt;&lt; nVar &lt;&lt; &quot;.&quot; &lt;&lt; endl;</TT>
<TT>    IncrementVar( &amp;nVar );</TT>
<TT>    cout &lt;&lt; &quot;The value of nVar is now &quot; &lt;&lt; nVar &lt;&lt; &quot;.&quot; &lt;&lt; endl;</TT>

<TT>    return 0;</TT>
<TT>}</TT>

<TT>void IncrementVar( int* nVar )</TT>
<TT>{</TT>
<TT>    *nVar += 1;</TT>
<TT>}</TT>
</FONT></PRE>
<P>Figure 9.4 shows how the address is used to change the value of a variable outside
the function.</P>
<P><A NAME="04"></A><A HREF="04.htm"><B>Figure 9.4.</B> </A><I><BR>
Changing a variable's address outside a function.</I></P>
<P>Another use for pointers is to keep a reference to memory that has been requested
at runtime from the operating system. You will use pointers like this later, in the
section called &quot;Using <TT>new</TT> and <TT>delete</TT> to Create Dynamic Objects.&quot;
<H3><FONT COLOR="#000077"><B>Using References</B></FONT></H3>
<P>In addition to using pointers to refer to other variables, the C++ language also
has a derived type known as a <I>reference</I>. A reference is declared using the
reference operator <TT>&amp;</TT>, which bears an uncanny resemblance to the address-of
operator. Both operators use the same symbol; however, you use them in different
contexts. The only time <TT>&amp;</TT> is used for a reference is in a declaration,
like this:</P>
<PRE><FONT COLOR="#0066FF"><TT>int myAge;</TT>
<TT>int&amp; myRef = myAge;</TT>
</FONT></PRE>
<P>This code defines a reference variable named <TT>myRef</TT>, which is a reference,
or <I>alias</I>, for the <TT>myAge</TT> variable. The advantage of using a reference
instead of a pointer variable is that no indirection operator is required. However,
after it is defined, the reference variable cannot be bound to another variable.
For example, code such as that in Listing 9.6 often is misunderstood.
<H4><FONT COLOR="#000077">TYPE: Listing 9.6. Using references to change the value
of a variable.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>void refFunc()</TT>
<TT>{</TT>
<TT>    int nFoo = 5;</TT>
<TT>    int nBar = 10;</TT>

<TT>    // Define a reference to int that is an alias for nFoo.</TT>
<TT>    int&amp; nRef = nFoo;</TT>

<TT>    // Change the value of nFoo.</TT>
<TT>    nRef = nBar;</TT>

<TT>    CString strMsg;</TT>
<TT>    strMsg.Format(&quot;nFoo = %d, nBar = %d&quot;, nFoo, nBar);</TT>

<TT>    AfxMessageBox(strMsg);</TT>
<TT>}</TT>
</FONT></PRE>
<P>If you use the <TT>refFunc</TT> function in a Windows program, you will see that
the line</P>
<PRE><FONT COLOR="#0066FF"><TT>nRef = nFoo;</TT>
</FONT></PRE>
<P>does not change the binding of the <TT>nRef</TT> variable; instead, it assigns
the value of <TT>nBar</TT> to <TT>nFoo</TT>, with <TT>nFoo</TT> being the variable
to which <TT>nRef</TT> is a reference.</P>
<P>References are most commonly used when passing parameters to functions. Passing
a class object as a function parameter often is quite expensive in terms of computing
resources. Using a pointer to pass a parameter is subject to errors and affects the
function's readability. However, if you use references as function parameters, you
eliminate unnecessary copies, and you can use the parameter as if a copy were passed.
To prevent the called function from changing the value of a reference variable, you
can declare the parameter as <TT>const</TT>, like this:</P>
<PRE><FONT COLOR="#0066FF"><TT>void Print( const int&amp; nFoo )</TT>
<TT>{</TT>
<TT>    nFoo = 12;  // error - not allowed to change const</TT>
<TT>    cout &lt;&lt; &quot;The value is &quot; &lt;&lt; nFoo &lt;&lt; endl;</TT>
<TT>}</TT>
</FONT></PRE>


<BLOCKQUOTE>
	<P>
<HR>
<B> </B><FONT COLOR="#000077"><B>]Time Saver:</B></FONT><B> </B>References to <TT>const</TT>
	objects are often used when large objects are passed to a function because it can
	be expensive, in terms of computing resources, to generate a copy of a large object
	that is used only during a function call. 
<HR>


</BLOCKQUOTE>

<H3><FONT COLOR="#000077"><B>Using <TT>new</TT> and <TT>delete</TT> to Create Dynamic
Objects</B></FONT></H3>
<P>So far, you've learned about variables allocated as local objects that are created
when a function or block is entered and destroyed when the function or block is exited.
Most programs that work in the real world use variables and objects that have a <I>dynamic
lifetime</I>, meaning that they are explicitly created and explicitly destroyed.</P>
<P>In a C++ program, you can use the <TT>new</TT> and <TT>delete</TT> operators to
allocate and destroy variables dynamically, as shown in Listing 9.7.
<H4><FONT COLOR="#000077">TYPE: Listing 9.7. Using new and delete for fundamental
types.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>void ptrFunc()</TT>
<TT>{</TT>
<TT>    int *pFoo = new int;</TT>
<TT>    *pFoo = 42;</TT>

<TT>    CString strMsg;</TT>
<TT>    strMsg.Format(&quot;Foo = %d&quot;, *pFoo);</TT>
<TT>    AfxMessageBox(strMsg);</TT>

<TT>    delete pFoo;</TT>
<TT>}</TT>
</FONT></PRE>
<H3><FONT COLOR="#000077"><B>Using <TT>new[]</TT> and <TT>delete[]</TT> to Create
Arrays</B></FONT></H3>
<P>You also can create arrays dynamically using <TT>new[]</TT>, with the size of
the array specified inside the square brackets. When you create an array using <TT>new[]</TT>,
you must use <TT>delete[]</TT> to release the memory allocated for the array. The
size of the array is not specified when <TT>delete[]</TT> is used. Using <TT>delete[]</TT>
is the only clue to the compiler indicating that the pointer is the beginning of
an array of objects. Listing 9.8 is an example of a function showing how to allocate
and free a dynamic array.
<H4><FONT COLOR="#000077">TYPE: Listing 9.8. Using new[] to create a dynamic array.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>void ptrArrayFunc()</TT>
<TT>{</TT>
<TT>    // Create array</TT>
<TT>    const int nMaxFoo = 5;</TT>
<TT>    int *arFoo = new int[nMaxFoo];</TT>

<TT>    // Fill array</TT>
<TT>    for(int n = 0; n &lt; nMaxFoo; n++)</TT>
<TT>    {</TT>
<TT>        arFoo[n] = 42 + n;</TT>
<TT>    }</TT>

<TT>    // Read array</TT>
<TT>    for(n = 0; n &lt; nMaxFoo; n++ )</TT>
<TT>    {</TT>
<TT>        CString strMsg;</TT>
<TT>        strMsg.Format(&quot;Index %d = %d&quot;, n, arFoo[n]);</TT>
<TT>        AfxMessageBox(strMsg);</TT>
<TT>    }</TT>

<TT>    // Free array</TT>
<TT>    delete[] arFoo;</TT>
<TT>}</TT>
</FONT></PRE>
<P>Note that in Listing 9.8, it's possible to use a variable to specify the size
of the array.
<H3><FONT COLOR="#000077"><B>Using Pointers with Derived Classes</B></FONT></H3>
<P>An instance of a class can be allocated and used dynamically, just as if it were
one of the fundamental types, like this:</P>
<PRE><FONT COLOR="#0066FF"><TT>CRect* pRect = new CRect;</TT>
</FONT></PRE>
<P>This example allocates space for a <TT>CRect</TT> object and calls the <TT>CRect</TT>
constructor to perform any needed initializations. Of course, after the <TT>CRect</TT>
object is no longer needed, you should make sure that the program calls <TT>delete</TT>
to free the allocated memory and cause the class's destructor to be called.</P>
<PRE><FONT COLOR="#0066FF"><TT>delete pRect;</TT>
</FONT></PRE>
<P>When using a pointer to a class or structure, you use the member selection operator,
or <TT>-&gt;</TT>, to access member data and functions:</P>
<PRE><FONT COLOR="#0066FF"><TT>pRect-&gt;left = 0;</TT>
<TT>int nHeight = pRect-&gt;Height();</TT>
</FONT></PRE>
<H3><FONT COLOR="#000077"><B>Using a Pointer to a Base Class</B></FONT></H3>
<P>Because a class derived from a base class actually contains the base, it's possible
to use a pointer to a base class when working with a derived object. For example,
in the MFC library, you can use a pointer to a <TT>CWnd</TT> object in place of a
<TT>CDialog</TT> object. This makes a design much easier to implement because all
the functions that work with any type of window can just use pointers to <TT>CWnd</TT>
instead of trying to determine the type of each object. In other words, because <TT>CDialog</TT>
is a <TT>CWnd</TT>, you should be able to do this:</P>
<PRE><FONT COLOR="#0066FF"><TT>CWnd* pWnd = new CDialog(/*Initialization info deleted*/;</TT>
<TT>pWnd-&gt;EnableWindow();</TT>
</FONT></PRE>
<P>You might be wondering how this code works--after all, how does the compiler know
to call the <TT>CWnd</TT> version of <TT>EnableWindow</TT> or the <TT>CDialog</TT>
version of <TT>EnableWindow</TT>? In order to solve this problem, you must declare
functions used through base-class pointers as virtual functions. When a function
is declared with the <TT>virtual</TT> keyword, the compiler generates code that determines
the actual type of the object at runtime and calls the correct function.
<H3><FONT COLOR="#000077"><B>Using Virtual Functions</B></FONT></H3>
<P><FONT COLOR="#000077"><B>New Term:</B></FONT><B> </B>A <I>virtual function</I>
is a function that is resolved at runtime.</P>
<P>When a virtual function is used, the compiler constructs a special table, called
a <I>virtual function table</I>. This table is used to keep track of the correct
functions to be called for every object of that class. When a virtual function is
called, the virtual function table is used to access the correct function indirectly,
as shown in Figure 9.5.</P>
<P><A NAME="05"></A><A HREF="05.htm"><B>Figure 9.5.</B></A> <I><BR>
The virtual function table, used to determine the correct virtual function.</I></P>
<P>The added overhead of using the virtual function table is fairly small, but it
could be significant if you have thousands of small objects or if execution speed
is critical. For that reason, a function must be specified as <TT>virtual</TT>; it
doesn't happen by default. Listing 9.9 is an example of a class declaration that
uses a virtual function.
<H4><FONT COLOR="#000077">TYPE: Listing 9.9. An example of declaring a virtual function.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>class CUser</TT>
<TT>{</TT>
<TT>public:</TT>
<TT>    CUser();</TT>
<TT>    virtual void ClearInfo();</TT>
<TT>protected:</TT>
<TT>    // ...</TT>
<TT>};</TT>
</FONT></PRE>


<BLOCKQUOTE>
	<P>
<HR>
<B> </B><FONT COLOR="#000077"><B>Time Saver:</B></FONT><B> </B>The <TT>virtual</TT>
	keyword is used only in the class declaration, not in the function definition. 
<HR>


</BLOCKQUOTE>

<P><FONT COLOR="#000077"><B>New Term:</B></FONT><B> </B>When a base class declares
a virtual function, it sometimes makes no sense for the base class to provide any
implementation for the function. A base class that includes functions that are declared,
but are implemented in derived classes, is an <I>abstract class</I>.</P>
<P>To force all subclasses of a class to implement a virtual function, you can declare
that function as a &quot;pure&quot; virtual function by adding <TT>= 0;</TT> to its
declaration in the abstract class, as shown in Listing 9.10.
<H4><FONT COLOR="#000077">TYPE: Listing 9.10. An example of declaring a pure virtual
function.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>class CShape</TT>
<TT>{</TT>
<TT>public:</TT>
<TT>    virtual void Draw() = 0;</TT>
<TT>};</TT>
</FONT></PRE>
<H2><FONT COLOR="#000077"><B>Exploring Document/View Interfaces</B></FONT></H2>
<P>The most commonly used interfaces in a Document/View program handle communication
between the document and view objects, and between Windows and the document and view
objects. Each of these interfaces has a particular purpose. Some are always overridden
in the classes you include in your project; many are overridden only when needed.
These are three of the major interfaces used in a Document/View program:

<UL>
	<LI><TT>GetDocument</TT>, a <TT>CView</TT> member function used to retrieve a pointer
	to its document<BR>
	<BR>
	
	<LI><TT>UpdateAllViews</TT>, a <TT>CDocument</TT> member function used to update
	views associated with a document<BR>
	<BR>
	
	<LI><TT>OnNewDocument</TT>, a <TT>CDocument</TT> member function used to initialize
	the document's member data
</UL>

<P>Remember, this list is just an overview of the major interfaces. The list does
not cover all the interfaces required in an SDI or MDI program. Your mileage may
vary; after using the Document/View architecture for a while, you might have another

⌨️ 快捷键说明

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