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

📄 ch05.htm

📁 C++ From Scratch: An Object-Oriented Approach is designed to walk novice programmers through the ana
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<h4> Listing 5.3 Illustrating Pass by Value</h4><pre><tt>0:  #include &lt;iostream&gt;</tt><tt>1:  using namespace std;</tt><tt>2:  </tt><tt>3:  class Game</tt><tt>4:  {</tt><tt>5:  public:</tt><tt>6:      Game(){};</tt><tt>7:      ~Game(){}</tt><tt>8:      void Play();</tt><tt>9:      void Score(int correct, int position);</tt><tt>10:  </tt><tt>11:  private:</tt><tt>12:      int howManyLetters;</tt><tt>13:      int howManyPositions;</tt><tt>14:  };</tt><tt>15:  </tt><tt>16:  void Game::Score(int  correct, int  position)</tt><tt>17:  {</tt><tt>18:      cout &lt;&lt; "\nBeginning score. Correct: ";</tt><tt>19:      cout &lt;&lt; correct &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>20:      correct = 5;</tt><tt>21:      position = 7;</tt><tt>22:      cout &lt;&lt; "Departing score. Correct: ";</tt><tt>23:      cout &lt;&lt; correct &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>24:  }</tt><tt>25:  </tt><tt>26:   void Game::Play()</tt><tt>27:  {</tt><tt>28:      int correct = 0;</tt><tt>29:      int position = 0;</tt><tt>30:  </tt><tt>31:      cout &lt;&lt; "Beginning Play. Correct: ";</tt><tt>32:      cout &lt;&lt; correct &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>33:      correct = 2;</tt><tt>34:      position = 4;</tt><tt>35:      cout &lt;&lt; "Play updated values. Correct: " ;</tt><tt>36:      cout &lt;&lt; correct &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>37:      cout &lt;&lt; "\nCalling score..." &lt;&lt; endl;</tt><tt>38:      Score(correct, position);</tt><tt>39:      cout &lt;&lt; "\nBack from Score() in Play. Correct: ";</tt><tt>40:      cout &lt;&lt; correct &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>41:  }</tt><tt>42:  </tt><tt>43:  int main()</tt><tt>44:  {</tt><tt>45:  </tt><tt>46:      Game theGame;</tt><tt>47:      theGame.Play();</tt><tt>48:      return 0;</tt><tt>49:  }</tt><tt>50: Beginning Play. <tt>Correct</tt>: 0 <tt>Position</tt>: 0</tt><tt>51: Play updated values. <tt>Correct</tt>: 2 <tt>Position</tt>: 4</tt><tt>52:</tt><tt>53: Calling score...</tt><tt>54:</tt><tt>55: Beginning score. <tt>Correct</tt>: 2 <tt>Position</tt>: 4</tt><tt>56: Departing score. <tt>Correct</tt>: 5 <tt>Position</tt>: 7</tt><tt>57:</tt><tt>58: Back from <tt>Score() </tt>in Play. <tt>Correct</tt>: 2 <tt>Position</tt>: 4</tt></pre><p>The very first thing to note is that I've moved everything into one file: Decryptix.cpp.   This is for convenience only. In a real program, the declaration of <tt>Game</tt>   would be in Game.h, the implementation of Game would be in Game.cpp, and so   forth.</p><p>Let's examine the code. On line 6, you see that we've simplified the constructor   to take no action, and we've implemented it inline. For the purpose of this   illustration, we don't need to focus on anything except the invocation of <tt>Score()   </tt>from <tt>Play()</tt>. On line 9, you might notice that I've simplified the   signature of <tt>Score():</tt>, eliminating the array of characters. We'll come   back to how to pass an array into a function later, but for now I want to focus   on the two integer variables, <tt>correct </tt>and <tt>position</tt>. Note that   in this illustration the ampersand (&amp;) is gone: We're now passing by value,   not by reference.</p><p>Program flow begins in <tt>main()</tt>, toward the bottom of the file on line   43. On line 46 we create an instance of a <tt>Game</tt> object, and at (16)   we invoke (or call) the method <tt>Play()</tt> on that method.</p><p>This call to <tt>Play()</tt> causes program flow to jump to the beginning of   <tt>Play()</tt> on line 26. We start by initializing both <tt>correct</tt> and <tt>position</tt>   to <tt>0</tt>, on line 28. We then print these values on line 32, which is reflected   in the output on line 50. </p><p>Next, on lines 33 and 34 we change the values of <tt>correct</tt><tt> </tt>and   <tt>position</tt> to <tt>2</tt> and <tt>4</tt>, respectively, and then on line   36 we print them again, which is shown in the output on line 51. </p><p>On line 38 we invoke <tt>Score()</tt>, passing in <tt>correct</tt> and <tt>position</tt>.   This causes the program flow to jump to the implementation of <tt>Score()</tt>,   which is<tt> </tt>shown on lines 16-24.</p><p>The signature of <tt>Score() </tt>at its implementation matches that of <tt>Score()   </tt>in the class declaration, as it must. Thus, <tt>correct</tt> and <tt>position   </tt>are passed in by value. This is exactly as if you had declared local variables   in this function and initialized them to the values they had in <tt>Play()</tt>.</p><p>On line 19 we print <tt>correct</tt><tt> </tt>and <tt>position</tt> and, as the   output shows on line 55, they match the values they had in <tt>Play()</tt>.</p><p>On lines 20 and 21, we change these values to <tt>5</tt> and <tt>7</tt>, and   then on line 23 we print them again to prove that the change occurred; this   appears in the output at line 56.</p><p><tt>Score() </tt>now returns, and program flow resumes on 39; the values are   printed again, as shown in the output on line 58. </p><p>Until this moment, everything has proceeded according to plan; however, the   values back in <tt>Play()</tt> are not changed, even though you know they were   in <tt>Score()</tt>. Step through this in your debugger, and you'll find that   the values <i>are</i> changed in <tt>Score()</tt>, but when you are back in <tt>Play()</tt>,   they are unchanged.</p><p>As you have probably already guessed, this is the result of passing the parameters   by value. If you make one tiny change to this program and declare the values   to be passed by reference, this program works as expected (see Listing 5.4).</p><h4> Listing 5.4 Passing by Reference</h4><pre><tt>0:  #include &lt;iostream&gt;</tt><tt>1:  using namespace std;</tt><tt>2:  </tt><tt>3:  class Game</tt><tt>4:  {</tt><tt>5:  public:</tt><tt>6:      Game(){}</tt><tt>7:      ~Game(){}</tt><tt>8:      void Play();</tt><tt>9:      void Score(int &amp; correct, int &amp; position);</tt><tt>10:  </tt><tt>11:  private:</tt><tt>12:      int howManyLetters;</tt><tt>13:      int howManyPositions;</tt><tt>14:  };</tt><tt>15:  </tt><tt>16:  void Game::Score(int &amp; rCorrect, int &amp; rPosition)</tt><tt>17:  {</tt><tt>18:      cout &lt;&lt; "\nBeginning score. Correct: " &lt;&lt; rCorrect</tt><tt>18a:      &lt;&lt; " Position: " &lt;&lt; rPosition &lt;&lt; endl;</tt><tt>19:      rCorrect = 5;</tt><tt>20:      rPosition = 7;</tt><tt>21:  cout &lt;&lt; "Departing score. Correct: "; &lt;&lt; rCorrect;</tt><tt>21a: cout &lt;&lt; " Position: " &lt;&lt; rPosition &lt;&lt; endl;</tt><tt>22:  }</tt><tt>23:  </tt><tt>24:  void Game::Play()</tt><tt>25:  {</tt><tt>26:      int correct = 0;</tt><tt>27:      int position = 0;</tt><tt>28:  </tt><tt>29:      cout &lt;&lt; "Beginning Play. Correct: " &lt;&lt; correct;</tt><tt>29a:     cout &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>30:      correct = 2;</tt><tt>31:      position = 4;</tt><tt>32:      cout &lt;&lt; "Play updated values. Correct: " &lt;&lt; correct;</tt><tt>32a:     cout &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>33:      cout &lt;&lt; "\nCalling score..." &lt;&lt; endl;</tt><tt>34:      Score(correct, position);</tt><tt>35:      cout &lt;&lt; "\nBack from Score() in Play. Correct: " &lt;&lt; correct;</tt><tt>35a:     cout &lt;&lt; " Position: " &lt;&lt; position &lt;&lt; endl;</tt><tt>36:  }</tt><tt>37:  </tt><tt>38:  int main()</tt><tt>39:  {</tt><tt>40:  </tt><tt>41:      Game theGame;</tt><tt>42:      theGame.Play();</tt><tt>43:      return 0;</tt><tt>44:  }</tt><tt>45: Beginning Play. <tt>Correct</tt>: 0 <tt>Position</tt>: 0</tt><tt>46: Play updated values. <tt>Correct</tt>: 2 <tt>Position</tt>: 4</tt><tt>47:</tt><tt>48: Calling score...</tt><tt>49:</tt><tt>50: Beginning score. <tt>Correct</tt>: 2 <tt>Position</tt>: 4</tt><tt>51: Departing score. <tt>Correct</tt>: 5 <tt>Position</tt>: 7</tt><tt>52: </tt><tt>53: Back from <tt>Score() </tt>in Play. <tt>Correct</tt>: 5 <tt>Position</tt>: 7</tt></pre><p>The only change in this version is to the signature of <tt>Score() </tt>(on line   9), which is matched in the implementation (on line 16). The parameter names<i>   </i>(for example, <tt>r</tt><tt>Correct</tt>) need not match between the declaration   and the implementation.</p><blockquote>  <hr>  <p><strong>NOTE: </strong> The parameter names are actually optional at the     declaration. If you leave them off, the program compiles without error. As     a general programming practice, however, be sure to include good parameter     names even though they are not required. They serve as documentation and make     your source code easier to understand.</p>  <hr></blockquote><p>The invocation of <tt>Score()</tt> on line 34 does not change at all. The client   of <tt>Score() </tt>doesn't have to manage the fact that you are now passing <tt>correct</tt>   and <tt>position</tt> by reference. </p><p>The output illustrates on line 53 that the change to the values in <tt>Score()   </tt>did change the values back in <tt>Play()</tt>. This happens because this time   no copy was made--you were changing the actual values.</p><h3> <a name="Heading5">References and Passing by Reference</a></h3><p>The change in the signature is a change in type. You have changed <tt>correct</tt>   from the integer</p><pre><tt>int <tt>correct</tt></tt></pre><p>into a reference to an integer:</p><pre><tt>int &amp; r<tt>Correct</tt></tt></pre><p>A <i>reference</i> is a special type that acts as an alias. </p><blockquote>  <hr>  <p><strong>NOTE: </strong> A <i>reference</i> is a type that acts as an alias     to an existing object.</p>  <hr></blockquote><p>The references <tt>rCorrect</tt> and <tt>rPosition</tt> are used within <tt>Score()   </tt>exactly as if they were normal integer variables, but the values assigned   to them are actually assigned to the original variables--<tt>correct</tt> and   <tt>position</tt>--back in <tt>Play()</tt>.</p><blockquote>  <hr>  <p><strong>NOTE: </strong> The name I've given it, <tt>rCorrect</tt>, is a clue     to me that this is a reference. I tend to prepend reference variables with     the letter <i>r</i> and pointers (discussed later) with the letter <i>p</i>,     but the language does certainly not require this. You can name the variables     in <tt>Score()</tt> and the variables in <tt>Play()</tt> using exactly the     same names, but it makes the source code a bit more difficult to understand.</p>  <hr>  <hr>  <p> <b>prepend</b>--Programmers use the term <i>prepend</i> to indicate that     you add something to the beginning of a term or variable. Thus, we prepend     the letter <i>p</i> to variable names for pointers. The Free Online Dictionary     of Computing (<tt>http://www.instantweb.com/foldoc/foldoc.cgi?query=prepend</tt>)     defines <i>prepend</i> as follows: /pree <i>pend</i>/ (by analogy with <i>append</i>)     To prefix or add to the beginning.</p>  <hr></blockquote><p>It is important to distinguish between passing<i> by </i>reference and passing   <i>a</i> reference. There are two ways to pass by reference. So far we've examined   one way: using a reference. Let's take a look at the alternative--pointers.   <a name="_Toc444312805"></a></p><h2> <a name="Heading6">Pointers</a></h2><p>Your throat tightens, your pulse quickens, and a cold, sickening dread grows   in the pit of your stomach. Nothing unnerves new C++ programmers as does working   with pointers. Well, relax. When you understand that a pointer is nothing more   than a variable that holds the <i>address in memory</i> of another variable,   pointers are a piece of cake. <a name="_Toc444312806"></a></p><h3> <a name="Heading7">What is a pointer?</a></h3><p>When you create objects in your program, you create them in memory. </p><p>When you create the local variable <tt>correct</tt> in the method <tt>Play()</tt>,   <tt>correct</tt> is kept in memory. Later you'll examine where in memory variables   live, but for now it doesn't matter. What does matter is that <tt>correct</tt>   is in memory, and every location in memory has an address. Normally, you don't   care about the specific address of an object because you have a label (or name),   for example, <tt>correct</tt>. If you need to get to <tt>correct</tt>, you can do   so with its label. </p><p>You can get the address of <tt>correct</tt> by using the address of operator   (<tt>&amp;</tt>):</p><pre><tt>&amp;<tt>correct</tt>;</tt></pre><blockquote>  <hr>  <p><strong>NOTE: </strong> The address-of operator (<tt>&amp;</tt>) uses the     same ampersand that we used to identify references. The compiler can tell     which you want by context.</p>  <hr></blockquote><p>When you have the address of <tt>correct</tt>, you can stash that address in 

⌨️ 快捷键说明

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