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

📄 ch09.htm

📁 一本好的VC学习书,本人就是使用这本书开始学习的vc,希望能对大家有帮助
💻 HTM
📖 第 1 页 / 共 5 页
字号:
38:          cout &lt;&lt; &quot;Calling FunctionTwo...\n&quot;;39:          FunctionTwo(&amp;Frisky);40:     return 0;41:   }42:43:   // FunctionOne, passes by value44:   SimpleCat FunctionOne(SimpleCat theCat)45:   {46:                   cout &lt;&lt; &quot;Function One. Returning...\n&quot;;47:                   return theCat;48:   }49:50:   // functionTwo, passes by reference51:   SimpleCat* FunctionTwo (SimpleCat  *theCat)52:   {53:                   cout &lt;&lt; &quot;Function Two. Returning...\n&quot;;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 verysimplified <TT>SimpleCat</TT> class is declared on lines 6-12. The constructor, copyconstructor, and destructor all print an informative message so that you can tellwhen they've been called.<BR>On line 34, <TT>main()</TT> prints out a message, and that is seen on output line1. On line 35, a <TT>SimpleCat</TT> object is instantiated. This causes the constructorto 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>, whichcreates 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 asan 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 informativemessage, 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 constructorand producing line 6.</P><P>The return value from <TT>FunctionOne()</TT> is not assigned to any object, andso the temporary created for the return is thrown away, calling the destructor, whichproduces output line 7. Since <TT>FunctionOne()</TT> has ended, its local copy goesout 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 thenreturns the <TT>SimpleCat</TT> object, again by reference, and so again producesno calls to the constructor or destructor.</P><P>Finally, the program ends and <TT>Frisky</TT> goes out of scope, causing one finalcall to the destructor and printing output line 11.</P><P>The net effect of this is that the call to <TT>FunctionOne()</TT>, because itpassed the cat by value, produced two calls to the copy constructor and two to thedestructor, while the call to <TT>FunctionTwo()</TT> produced none.<H4 ALIGN="CENTER"><A NAME="Heading34"></A><FONT COLOR="#000077">Passing a constPointer</FONT></H4><P>Although passing a pointer to <TT>FunctionTwo()</TT> is more efficient, it isdangerous. <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>. Thisseriously exposes the object to change and defeats the protection offered in passingby value.</P><P>Passing by value is like giving a museum a photograph of your masterpiece insteadof 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 invitingguests 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>. Doingso prevents calling any non-<TT>const</TT> method on <TT>SimpleCat</TT>, and thusprotects 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. Passingconst pointers.</B></FONT><PRE><FONT COLOR="#0066FF">1:  //Listing 9.112:       // Passing pointers to objects3:4:         #include &lt;iostream.h&gt;5:6:         class SimpleCat7:         {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 pointer59:    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 oldFrisky is 5 years oldCalling FunctionTwo...FunctionTwo. Returning...Frisky is now 5 years oldFrisky is 5 years oldSimple 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 theirmessages. The copy constructor is never called, however, because the object is passedby reference and so no copies are made. On line 41, an object is created, and itsdefault age is printed, starting on line 42.</P><P>On line 46, <TT>itsAge</TT> is set using the accessor <TT>SetAge</TT>, and theresult 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; theparameter and return value are now declared, on line 36, to take a constant pointerto 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 copiesare 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 wouldnot 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 declaresthe 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 anAlternative</FONT></H4><P>Listing 9.11 solves the problem of making extra copies, and thus saves the callsto 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 somewhatcumbersome, 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 within the function if a reference were passed in, rather than a pointer. Listing 9.12illustrates this.</P><P><A NAME="Heading38"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 9.12. Passingreferences to objects.</B></FONT><PRE><FONT COLOR="#0066FF">1: //Listing 9.122: // Passing references to objects3:4:   #include &lt;iostream.h&gt;5:6:   class SimpleCat7:   {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 object53:      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">Output: Making a cat...Simple Cat constructor...Frisky is 1 years oldFrisky is 5 years oldCalling FunctionTwo...FunctionTwo. Returning...Frisky is now 5 years oldFrisky is 5 years oldSimple Cat Destructor...</FONT></PRE><P><FONT COLOR="#000077"><TT><B>Analysis:</B></TT></FONT><TT><B> </B></TT>The outputis identical to that produced by Listing 9.11. The only significant change is that<TT>FunctionTwo()</TT> now takes and returns a reference to a constant object. Onceagain, working with references is somewhat simpler than working with pointers, andthe same savings and efficiency are achieved, as well as the safety provided by using<TT>const</TT>.<H3 ALIGN="CENTER"><A NAME="Heading40"></A><FONT COLOR="#000077">const References</FONT></H3><P>C++ programmers do not usually differentiate between &quot;constant referenceto a <TT>SimpleCat</TT> object&quot; and &quot;reference to a constant <TT>SimpleCat</TT>object.&quot; References themselves can never be reassigned to refer to another object,and so are always constant. If the keyword <TT>const</TT> is applied to a reference,it is to make the object referred to constant.<H3 ALIGN="CENTER"><A NAME="Heading41"></A><FONT COLOR="#000077">When to Use Referencesand When to Use Pointers</FONT></H3><P>C++ programmers strongly prefer references to pointers. References are cleaner

⌨️ 快捷键说明

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