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

📄 ch09.htm

📁 vc的电子书
💻 HTM
📖 第 1 页 / 共 5 页
字号:
20:   {
21:          cout << "Simple Cat Copy Constructor...\n";
22:   }
23:
24:   SimpleCat::~SimpleCat()
25:   {
26:          cout << "Simple Cat Destructor...\n";
27:   }
28:
29:   SimpleCat FunctionOne (SimpleCat theCat);
30:   SimpleCat* FunctionTwo (SimpleCat *theCat);
31:
32:   int main()
33:   {
34:          cout << "Making a cat...\n";
35:          SimpleCat Frisky;
36:          cout << "Calling FunctionOne...\n";
37:          FunctionOne(Frisky);
38:          cout << "Calling FunctionTwo...\n";
39:          FunctionTwo(&Frisky);
40:     return 0;
41:   }
42:
43:   // FunctionOne, passes by value
44:   SimpleCat FunctionOne(SimpleCat theCat)
45:   {
46:                   cout << "Function One. Returning...\n";
47:                   return theCat;
48:   }
49:
50:   // functionTwo, passes by reference
51:   SimpleCat* FunctionTwo (SimpleCat  *theCat)
52:   {
53:                   cout << "Function Two. Returning...\n";
54:                   return theCat;
<TT>55: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: 1:  Making a cat...
2:  Simple Cat Constructor...
3:  Calling FunctionOne...
4:  Simple Cat Copy Constructor...
5:  Function One. Returning...
6:  Simple Cat Copy Constructor...
7:  Simple Cat Destructor...
8:  Simple Cat Destructor...
9:  Calling FunctionTwo...
10: Function Two. Returning...
11: Simple Cat Destructor...
</FONT></PRE>


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Line numbers will not print. They
	were added to aid in the analysis. 
<HR>


</BLOCKQUOTE>

<P><FONT COLOR="#000077"><TT><B>Anaylsis:</B></TT></FONT><TT><B> </B></TT>A very
simplified <TT>SimpleCat</TT> class is declared on lines 6-12. The constructor, copy
constructor, and destructor all print an informative message so that you can tell
when they've been called.<BR>
On line 34, <TT>main()</TT> prints out a message, and that is seen on output line
1. On line 35, a <TT>SimpleCat</TT> object is instantiated. This causes the constructor
to be called, and the output from the constructor is seen on output line 2.</P>
<P>On line 36, <TT>main()</TT> reports that it is calling <TT>FunctionOne</TT>, which
creates output line 3. Because <TT>FunctionOne()</TT> is called passing the <TT>SimpleCat</TT>
object by value, a copy of the <TT>SimpleCat</TT> object is made on the stack as
an object local to the called function. This causes the copy constructor to be called,
which creates output line 4.</P>
<P>Program execution jumps to line 46 in the called function, which prints an informative
message, output line 5. The function then returns, and returns the <TT>SimpleCat</TT>
object by value. This creates yet another copy of the object, calling the copy constructor
and producing line 6.</P>
<P>The return value from <TT>FunctionOne()</TT> is not assigned to any object, and
so the temporary created for the return is thrown away, calling the destructor, which
produces output line 7. Since <TT>FunctionOne()</TT> has ended, its local copy goes
out of scope and is destroyed, calling the destructor and producing line 8.</P>
<P>Program execution returns to <TT>main()</TT>, and <TT>FunctionTwo()</TT> is called,
but the parameter is passed by reference. No copy is produced, so there's no output.
<TT>FunctionTwo()</TT> prints the message that appears as output line 10 and then
returns the <TT>SimpleCat</TT> object, again by reference, and so again produces
no calls to the constructor or destructor.</P>
<P>Finally, the program ends and <TT>Frisky</TT> goes out of scope, causing one final
call to the destructor and printing output line 11.</P>
<P>The net effect of this is that the call to <TT>FunctionOne()</TT>, because it
passed the cat by value, produced two calls to the copy constructor and two to the
destructor, while the call to <TT>FunctionTwo()</TT> produced none.
<H4 ALIGN="CENTER"><A NAME="Heading34"></A><FONT COLOR="#000077">Passing a const
Pointer</FONT></H4>
<P>Although passing a pointer to <TT>FunctionTwo()</TT> is more efficient, it is
dangerous. <TT>FunctionTwo()</TT> is not allowed to change the <TT>SimpleCat</TT>
object it is passed, yet it is given the address of the <TT>SimpleCat</TT>. This
seriously exposes the object to change and defeats the protection offered in passing
by value.</P>
<P>Passing by value is like giving a museum a photograph of your masterpiece instead
of the real thing. If vandals mark it up, there is no harm done to the original.
Passing by reference is like sending your home address to the museum and inviting
guests to come over and look at the real thing.</P>
<P>The solution is to pass a <TT>const</TT> pointer to <TT>SimpleCat</TT>. Doing
so prevents calling any non-<TT>const</TT> method on <TT>SimpleCat</TT>, and thus
protects the object from change. Listing 9.11 demonstrates this idea.</P>

<P><A NAME="Heading35"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 9.11. Passing
const pointers.</B></FONT>
<PRE><FONT COLOR="#0066FF">
1:  //Listing 9.11
2:       // Passing pointers to objects
3:
4:         #include &lt;iostream.h&gt;
5:
6:         class SimpleCat
7:         {
8:         public:
9:                 SimpleCat();
10:                 SimpleCat(SimpleCat&amp;);
11:                 ~SimpleCat();
12:
13:                 int GetAge() const { return itsAge; }
14:                 void SetAge(int age) { itsAge = age; }
15:
16:         private:
17:                 int itsAge;
18:            };
19:
20:            SimpleCat::SimpleCat()
21:            {
22:                   cout &lt;&lt; &quot;Simple Cat Constructor...\n&quot;;
23:                   itsAge = 1;
24:            }
25:
26:            SimpleCat::SimpleCat(SimpleCat&amp;)
27:            {
28:                   cout &lt;&lt; &quot;Simple Cat Copy Constructor...\n&quot;;
29:            }
30:
31:            SimpleCat::~SimpleCat()
32:            {
33:                   cout &lt;&lt; &quot;Simple Cat Destructor...\n&quot;;
34:            }
35:
36:const SimpleCat * const FunctionTwo (const SimpleCat * const theCat);
37:
38:            int main()
39:            {
40:                   cout &lt;&lt; &quot;Making a cat...\n&quot;;
41:                   SimpleCat Frisky;
42:                   cout &lt;&lt; &quot;Frisky is &quot; ;
43                    cout &lt;&lt; Frisky.GetAge();
44:                   cout &lt;&lt; &quot; years _old\n&quot;;
45:                   int age = 5;
46:                   Frisky.SetAge(age);
47:                   cout &lt;&lt; &quot;Frisky is &quot; ;
48                    cout &lt;&lt; Frisky.GetAge();
49:                   cout &lt;&lt; &quot; years _old\n&quot;;
50:                   cout &lt;&lt; &quot;Calling FunctionTwo...\n&quot;;
51:                   FunctionTwo(&amp;Frisky);
52:                   cout &lt;&lt; &quot;Frisky is &quot; ;
53                    cout &lt;&lt; Frisky.GetAge();
54:                   cout &lt;&lt; &quot; years _old\n&quot;;
55:     return 0;
56:            }
57:
58:    // functionTwo, passes a const pointer
59:    const SimpleCat * const FunctionTwo (const SimpleCat * const theCat)
60:    {
61:             cout &lt;&lt; &quot;Function Two. Returning...\n&quot;;
62:             cout &lt;&lt; &quot;Frisky is now &quot; &lt;&lt; theCat-&gt;GetAge();
63:             cout &lt;&lt; &quot; years old \n&quot;;
64:             // theCat-&gt;SetAge(8);   const!
65:             return theCat;
<TT>66: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: Making a cat...
Simple Cat constructor...
Frisky is 1 years old
Frisky is 5 years old
Calling FunctionTwo...
FunctionTwo. Returning...
Frisky is now 5 years old
Frisky is 5 years old
Simple Cat Destructor...
</FONT></PRE>
<P><FONT COLOR="#000077"><TT><B>Anaylsis:</B></TT></FONT><TT><B> </B>SimpleCat</TT>
has added two accessor functions, <TT>GetAge()</TT> on line 13, which is a <TT>const</TT>
function, and <TT>SetAge()</TT> on line 14, which is not a <TT>const</TT> function.
It has also added the member variable <TT>itsAge</TT> on line 17.<BR>
The constructor, copy constructor, and destructor are still defined to print their
messages. The copy constructor is never called, however, because the object is passed
by reference and so no copies are made. On line 41, an object is created, and its
default age is printed, starting on line 42.</P>
<P>On line 46, <TT>itsAge</TT> is set using the accessor <TT>SetAge</TT>, and the
result is printed on line 47. <TT>FunctionOne</TT> is not used in this program, but
<TT>FunctionTwo()</TT> is called. <TT>FunctionTwo()</TT> has changed slightly; the
parameter and return value are now declared, on line 36, to take a constant pointer
to a constant object and to return a constant pointer to a constant object.</P>
<P>Because the parameter and return value are still passed by reference, no copies
are made and the copy constructor is not called. The pointer in <TT>FunctionTwo()</TT>,
however, is now constant, and thus cannot call the non-<TT>const</TT> method, <TT>SetAge()</TT>.
If the call to <TT>SetAge()</TT> on line 64 was not commented out, the program would
not compile.</P>
<P>Note that the object created in <TT>main()</TT> is not constant, and <TT>Frisky</TT>
can call <TT>SetAge()</TT>. The address of this non-constant object is passed to
<TT>FunctionTwo()</TT>, but because <TT>FunctionTwo()</TT>'s declaration declares
the pointer to be a constant pointer, the object is treated as if it were constant!
<H4 ALIGN="CENTER"><A NAME="Heading37"></A><FONT COLOR="#000077">References as an
Alternative</FONT></H4>
<P>Listing 9.11 solves the problem of making extra copies, and thus saves the calls
to the copy constructor and destructor. It uses constant pointers to constant objects,
and thereby solves the problem of the function changing the object. It is still somewhat
cumbersome, however, because the objects passed to the function are pointers.</P>
<P>Since you know the object will never be null, it would be easier to work with
in the function if a reference were passed in, rather than a pointer. Listing 9.12
illustrates this.</P>

<P><A NAME="Heading38"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 9.12. Passing
references to objects.</B></FONT>
<PRE><FONT COLOR="#0066FF">
1: //Listing 9.12
2: // Passing references to objects
3:
4:   #include &lt;iostream.h&gt;
5:
6:   class SimpleCat
7:   {
8:   public:
9:           SimpleCat();
10:           SimpleCat(SimpleCat&amp;);
11:           ~SimpleCat();
12:
13:           int GetAge() const { return itsAge; }
14:           void SetAge(int age) { itsAge = age; }
15:
16:   private:
17:           int itsAge;
18:      };
19:
20:      SimpleCat::SimpleCat()
21:      {
22:             cout &lt;&lt; &quot;Simple Cat Constructor...\n&quot;;
23:             itsAge = 1;
24:      }
25:
26:      SimpleCat::SimpleCat(SimpleCat&amp;)
27:      {
28:             cout &lt;&lt; &quot;Simple Cat Copy Constructor...\n&quot;;
29:      }
30:
31:      SimpleCat::~SimpleCat()
32:      {
33:             cout &lt;&lt; &quot;Simple Cat Destructor...\n&quot;;
34:      }
35:
36:      const     SimpleCat &amp; FunctionTwo (const SimpleCat &amp; theCat);
37:
38:      int main()
39:      {
40:             cout &lt;&lt; &quot;Making a cat...\n&quot;;
41:             SimpleCat Frisky;
42:             cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky.GetAge() &lt;&lt; &quot; years old\n&quot;;
43:             int age = 5;
44:             Frisky.SetAge(age);
45:             cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky.GetAge() &lt;&lt; &quot; years old\n&quot;;
46:             cout &lt;&lt; &quot;Calling FunctionTwo...\n&quot;;
47:             FunctionTwo(Frisky);
48:             cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky.GetAge() &lt;&lt; &quot; years old\n&quot;;
49:     return 0;
50:      }
51:
52:      // functionTwo, passes a ref to a const object
53:      const SimpleCat &amp; FunctionTwo (const SimpleCat &amp; theCat)
54:      {
55:                      cout &lt;&lt; &quot;Function Two. Returning...\n&quot;;
56:                      cout &lt;&lt; &quot;Frisky is now &quot; &lt;&lt; theCat.GetAge();
57:                      cout &lt;&lt; &quot; years old \n&quot;;
58:                      // theCat.SetAge(8);   const!
59:                      return theCat;
<TT>60: }</TT></FONT>
<FONT COLOR="#0066FF">

⌨️ 快捷键说明

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