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

📄 ch05.htm

📁 C++ From Scratch: An Object-Oriented Approach is designed to walk novice programmers through the ana
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<tt>     return solution; </tt><tt>}</tt></pre><p>the compiler invisibly turns it into</p><pre><tt>const char * Game::GetSolution(<b>Game * this</b>) </tt><tt>{ </tt><tt>     return <b>this-&gt;</b>solution; </tt><tt>}</tt></pre><p>You are free to use the <tt>this</tt> pointer explicitly: you can write your   code as follows</p><pre><tt>const char * Game::GetSolution() </tt><tt>{ </tt><tt>     return <b>this-&gt;</b>solution; </tt><tt>}</tt></pre><p>but there is little point in doing so. That said, there are times when you   will use the <tt>this</tt> pointer explicitly to obtain the address of the object   itself. We'll discuss this later in the book.</p><p>When you declare the member method <tt>const</tt>, the compiler changes the   <tt>this</tt> pointer from a pointer to an object into a pointer to a <i>constant</i>   object. Thus, the compiler turns the following code</p><pre><tt>const char * Game::GetSolution() <b>const </b></tt><tt>{ </tt><tt>     return solution; </tt><tt>}</tt></pre><p>into</p><pre><tt>const char * Game::GetSolution(<b>const Game * this</b>) <b>const</b> </tt><tt>{ </tt><tt>     return <b>this-&gt;</b>solution; </tt><tt>}</tt></pre><p>The constant <tt>this</tt> pointer enforces the constancy of class <tt>method</tt>.</p><h3> <a name="Heading13">Arrays as Pointers</a></h3><p>The name of an array (in our case, <tt>guess</tt>) is thought of as a pointer   to the first element in the array. You can access elements of an array using   the offset operator (<tt>[]</tt>), or by using the name of the array and what   is called <i>pointer arithmetic.</i> Listing 5.7 illustrates this relationship   between pointers and arrays.</p><blockquote>  <hr>  <p><strong> </strong> <b>pointer</b> <b>arithmetic</b>--You can determine how     many objects are in a range by subtracting the address of one pointer from     another.</p>  <hr></blockquote><h4> Listing 5.7 Relationship Between Pointers and Arrays</h4><pre><tt>0:  #include &lt;iostream&gt;</tt><tt>1:  using namespace std;</tt><tt>2:  </tt><tt>3:  int main()</tt><tt>4:  {</tt><tt>5:      char myString[80];</tt><tt>6:      strcpy(myString,"Hello there");</tt><tt>7:      cout &lt;&lt; "myString is " &lt;&lt; strlen(myString)</tt><tt>7a:       &lt;&lt; " characters long!" &lt;&lt; endl;</tt><tt>8:      cout &lt;&lt; "myString: " &lt;&lt; myString &lt;&lt; endl;</tt><tt>9:      char c1 = myString[1];</tt><tt>10:      char c2 = *(myString + 1);</tt><tt>11:      cout &lt;&lt; "c1: " &lt;&lt; c1 &lt;&lt; " c2: " &lt;&lt; c2 &lt;&lt; endl;</tt><tt>12:      char * p1 = myString;</tt><tt>13:      char * p2 = myString + 1;</tt><tt>14:      cout &lt;&lt; "p1: " &lt;&lt; p1 &lt;&lt; endl;</tt><tt>15:      cout &lt;&lt; "p2: " &lt;&lt; p2 &lt;&lt; endl;</tt><tt>16:      cout &lt;&lt; "myString+1: " &lt;&lt; myString+1 &lt;&lt; endl;</tt><tt>17:      myString[4] = 'a';</tt><tt>18:      cout &lt;&lt; "myString: " &lt;&lt; myString &lt;&lt; endl;</tt><tt>19:      *(myString+4) = 'b';</tt><tt>20:      cout &lt;&lt; "myString: " &lt;&lt; myString &lt;&lt; endl;</tt><tt>21:      p1[4] = 'c';</tt><tt>22:      cout &lt;&lt; "myString: " &lt;&lt; myString &lt;&lt; endl;</tt><tt>23:      *(p1+4) = 'd';</tt><tt>24:      cout &lt;&lt; "myString: " &lt;&lt; myString &lt;&lt; endl;</tt><tt>25:      myString[4] = 'o';</tt><tt>26:      myString[5] = '\0';</tt><tt>27:      cout &lt;&lt; "myString: " &lt;&lt; myString &lt;&lt; endl;</tt><tt>28:      return 0;</tt><tt>29:  }</tt><tt>30: myString is 11 characters long!</tt><tt>31: myString: Hello there</tt><tt>32: c1: e c2: e</tt><tt>33: p1: Hello there</tt><tt>34: p2: ello there</tt><tt>35: myString+1: ello there</tt><tt>36: myString: Hella there</tt><tt>37: myString: Hellb there</tt><tt>38: myString: Hellc there</tt><tt>39: myString: Helld there</tt><tt>40: myString: Hello</tt></pre><p>On line 5, we create a character array that is large enough to hold the string.   On line 6 we use the old-fashioned C-style string library routine <tt>strcpy</tt>   to copy into our array a null-terminated string with the words <i>Hello there</i>.</p><p>On line 7 we use the C-style library routine <tt>strlen</tt> to obtain the   length of the string. This measures the number of characters until the first   <tt>NULL</tt> and returns that value (11) as an integer, which is printed by   <tt>cout</tt> and shown on line 30.</p><p>On line 8 we pass the array to <tt>cout</tt>, which treats the name of the   array (<tt>myString</tt>) as a pointer to the first byte of the string. <tt>cout</tt>   knows that when it is given an array name it is to print every character until   the first <tt>NULL</tt>. This is shown on line 30.</p><p>On line 9 we create a character variable, <tt>c1</tt>, which is initialized   with the character at offset <tt>1</tt>--that is, the second character in the   array, <tt>e</tt>.</p><p>On line 13 we treat <tt>myString</tt> as a pointer and add one to it. When   you add one to a pointer, the compiler looks at the type of the object that   is pointed to, which in this case is <tt>char</tt>. It uses the type to determine   the size of the object, which in this case is one byte. It then returns the   address of the next object of that size. If this were a pointer to <tt>int</tt>,   it would return the address of the next <tt>int</tt>, four bytes later in memory.</p><p>Take the address that is returned (<tt>myString+1</tt>) and dereference it;   this returns the character at that address. Then initialize a new character   variable, <tt>c2</tt>, with that character. Note that <tt>c2</tt> is not a pointer;   by dereferencing, you're actually getting a character, and that is what is assigned   to <tt>c2</tt>. </p><p>We print these two characters on line 11, and the printout is on line 32.</p><p>On line 12 we create a pointer to a character and assign it to <tt>myString</tt>.   Because the name of the array acts as a pointer to the first byte of the array,   <tt>p1</tt> now also points to the first byte. On line 13 we create a second   pointer and point it to the second character in the array. These are printed   on lines 14 and 15 and shown at lines 33 and 34). This illustrates that in each   case <tt>cout</tt> acts as expected, printing the string beginning at the byte   that is pointed to and continuing until the first <tt>NULL</tt>. These have   the same printout as on line 18, which uses the string offset directly and which   is shown on line 35.</p><p>On line 21 we use the offset operator to change the character that is stored   at offset <tt>4</tt> (the fifth character). This is printed, and the output   appears on line 36.</p><p>You can accomplish the same thing on line 16 by using pointer arithmetic and   dereferencing the address that is returned; see the output on line 37. Because   <tt>p1</tt> is pointing to <tt>myString</tt>, you can use the offset operator   on the pointer on line 21. Remember that the name of the array is a pointer   to the first element--and that is exactly what <tt>p1</tt> is. The effect on   line 38 is identical.</p><p>Similarly, on line 23 we can use pointer arithmetic on <tt>p1</tt> and then   dereference the resulting address, just as we did with the array name. The resulting   printout is shown on line 39.</p><p>On line 25 we change the value back to <tt>'o'</tt> using the offset operator,   and then we insert a null at offset 5. You can do the same thing with pointer   arithmetic, but you get the point. As you probably remember, <tt>cout</tt> prints   only to the first null, so the string <tt>hello</tt> is printed; nothing further   in the array is printed, however, even though the word <i>there</i> still remains.   This is shown on line 40.</p><h3> <a name="Heading14">Passing the Array as a Pointer</a></h3><p>We said earlier that <tt>guess</tt> is passed by reference, as a pointer. What   you see passed in Listing 5.6 is the name of the array, which is a pointer to   the first element in the array:</p><p> Score(guess,<tt>correct</tt>,<tt>position</tt>);In <tt>Score()</tt> this first parameter   must be declared as a pointer to character, which it is. Listing 5.8 reproduces   Listing 5.1, the declaration of the <tt>Game</tt> class.</p><h4> Listing 5.8 Reproducing Listing 5.1</h4><pre><tt>0:  #ifndef GAME_H</tt><tt>1:  #define GAME_H</tt><tt>2:  </tt><tt>3:  #include "definedValues.h"</tt><tt>4:  </tt><tt>5:  class Game</tt><tt>6:  {</tt><tt>7:  public:</tt><tt>8:      Game();</tt><tt>9:      ~Game(){}</tt><tt>10:      void Display(const char * charArray)const{ cout &lt;&lt; charArray &lt;&lt;</tt><tt>10a:                                            endl;}</tt><tt>11:    void Play();</tt><tt>12:    const char * GetSolution() const { return solution; }</tt><tt>13:    void Score(const char * thisGuess, int &amp; correct, int &amp; position);</tt><tt>14:  </tt><tt>15:  private:</tt><tt>16:      int howMany(const char *, char);</tt><tt>17:      char solution[maxPos];</tt><tt>18:      int howManyLetters;</tt><tt>19:      int howManyPositions;</tt><tt>20:      int round;</tt><tt>21:      bool duplicates;</tt><tt>22:  };</tt><tt>23:  </tt><tt>24:  #endif</tt></pre><p>You can see on line 13 that the first parameter to <tt>Score() </tt>is declared   as a pointer to <tt>char</tt>, just as we require. Listing 5.9 shows the implementation   of the <tt>Score() </tt>method.</p><h4> Listing 5.9 Implementing Score()</h4><pre><tt>0:void Game::Score(const char * thisGuess, int &amp; correct, int &amp; position)</tt><tt>1:  {</tt><tt>2:      correct = 0;</tt><tt>3:      position = 0;</tt><tt>4:  </tt><tt>5:      for ( int i = 0; i &lt; howManyLetters; i++)</tt><tt>6:      {</tt><tt>7:          int howManyInGuess = howMany (thisGuess, alpha[i]);</tt><tt>8:          int howManyInAnswer = howMany (solution, alpha[i]);</tt><tt>9:          correct += howManyInGuess &lt; howManyInAnswer ? </tt><tt>10:                          howManyInGuess : howManyInAnswer;</tt><tt>11:  </tt><tt>12:      }</tt><tt>13:  </tt><tt>14:      for ( int j = 0; j &lt; howManyPositions; j++)</tt><tt>15:      {</tt><tt>16:          if ( thisGuess[j] == solution[j] )</tt><tt>17:              position++;</tt><tt>18:      }</tt><tt>19:  </tt><tt>20:  }</tt></pre><p>The signature on the implementation agrees, as it must, with the declaration.   <tt>thisGuess</tt> is a pointer to <tt>char</tt> and is the same array as <tt>guess</tt>   in <tt>Play()</tt>. Because <tt>guess</tt> was passed by reference (as arrays   must be), this is the same array, and changes to this array are reflected back   in <tt>Play</tt>.</p><p>Because you must pass by reference but you do not want to allow <tt>Score()   </tt>to change this array (and there is no reason for it to do so), declare the   parameter to be a pointer to a constant <tt>char</tt> rather than a pointer   to <tt>char</tt>. This keyword <tt>const</tt> says to the compiler, "I don't   intend to change the object that is pointed to, so tell me if I do." This way,   the compiler taps you on the shoulder if you attempt to make such a change and   says, "Excuse me, sir, but you've changed an object when you promised you wouldn't.   Not cricket, sir." (Your compiler's error message might vary).</p><p>Let's walk through this implementation of <tt>Score()</tt> line by line. On lines   2 and 3, we initialize both integers, <tt>correct</tt><tt> </tt>and <tt>position</tt><tt>,</tt>   to <tt>0</tt>. If we take no other action, the score<tt> </tt>is zero correct   and zero in position. </p><p>On line 5 we begin a <tt>for</tt> loop that will run once for each letter in   <tt>thisGuess</tt>. The body of the <tt>for</tt> loop consists of three statements.</p><p>On line 7 a local variable--<tt>howManyInGuess</tt>--is initialized to store   the result of calling the private member method <tt>howMany(). When we call   howMany, we pass</tt> in the pointer to the array as the first parameter and   the letter at <tt>alpha[i]</tt> as the second parameter.</p><p>This is a classic C++ statement, which does at least three things at once.   Let's take the statement apart. </p><p>The first thing that happens is that <tt>alpha[i]</tt> is returned. The first   time through this loop, <tt>alpha[0]</tt> is returned, which is <tt>'a'</tt>.   The second time through, <tt>'b'</tt> is returned, and so forth.</p><p>This letter becomes the second parameter to the call to <tt>howMany()</tt>.   If you look back at the declaration of <tt>Game</tt>, you'll find that <tt>howMany()</tt>   is a private method that takes two parameters: a pointer to a constant <tt>char</tt>   (the guess from <tt>Play()</tt>) and a character. Listing 5.10 shows the implementation   of <tt>howMany()</tt>.</p><h4> Listing 5.10 Implementing Game::HowMany()</h4><pre><tt>    </tt><tt>0:  inline int Game::howMany(const char * theString, char c)</tt><tt>1:  {</tt><tt>2:      int count = 0;</tt><tt>3:      for ( int i = 0; i &lt; strlen(theString); i++)</tt><tt>4:    {</tt><tt>5:          if ( theString[i] == c )</tt><tt>6:              count ++;</tt><tt>7:    }</tt><tt>8:      return count;</tt></pre><p>9: }The purpose of this method is to return the number of times an individual 

⌨️ 快捷键说明

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