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

📄 ch08.htm

📁 一本好的VC学习书,本人就是使用这本书开始学习的vc,希望能对大家有帮助
💻 HTM
📖 第 1 页 / 共 5 页
字号:
1:     // Listing 8.62:     // Accessing data members of objects on the heap3:4:      #include &lt;iostream.h&gt;5:6:      class SimpleCat7:      {8:      public:9:             SimpleCat() {itsAge = 2; }10:             ~SimpleCat() {}11:             int GetAge() const { return itsAge; }12:             void SetAge(int age) { itsAge = age; }13:     private:14:             int itsAge;15:        };16:17:        int main()18:        {19:               SimpleCat * Frisky = new SimpleCat;20:               cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky-&gt;GetAge() &lt;&lt; &quot; years old\n&quot;;21:               Frisky-&gt;SetAge(5);22:               cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky-&gt;GetAge() &lt;&lt; &quot; years old\n&quot;;23:               delete Frisky;24:        return 0;<TT>25: }</TT></FONT><FONT COLOR="#0066FF">Output: Frisky is 2 years oldFrisky is 5 years old</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>In line 19, a <TT>SimpleCat</TT>object is instantiated on the free store. The default constructor sets its age to<TT>2</TT>, and the <TT>GetAge()</TT> method is called in line 20. Because this isa pointer, the indirection operator (<TT>-&gt;</TT>) is used to access the memberdata and functions. In line 21, the <TT>SetAge()</TT> method is called, and <TT>GetAge()</TT>is accessed again in line 22.<H3 ALIGN="CENTER"><A NAME="Heading33"></A><FONT COLOR="#000077">Member Data on theFree Store</FONT></H3><P>One or more of the data members of a class can be a pointer to an object on thefree store. The memory can be allocated in the class constructor or in one of itsmethods, and it can be deleted in its destructor, as Listing 8.7 illustrates.</P><P><A NAME="Heading34"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.7. Pointersas member data.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:  // Listing 8.72:  // Pointers as data members3:4:    #include &lt;iostream.h&gt;5:6:    class SimpleCat7:    {8:    public:9:            SimpleCat();10:            ~SimpleCat();11:            int GetAge() const { return *itsAge; }12:            void SetAge(int age) { *itsAge = age; }13:14:            int GetWeight() const { return *itsWeight; }15:            void setWeight (int weight) { *itsWeight = weight; }16:17:    private:18:            int * itsAge;19:            int * itsWeight;20:       };21:22:       SimpleCat::SimpleCat()23:       {24:            itsAge = new int(2);25:            itsWeight = new int(5);26:       }27:28:       SimpleCat::~SimpleCat()29:       {30:            delete itsAge;31:            delete itsWeight;32:       }33:34:       int main()35:       {36:              SimpleCat *Frisky = new SimpleCat;37:              cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky-&gt;GetAge() &lt;&lt; &quot; years old\n&quot;;38:              Frisky-&gt;SetAge(5);39:              cout &lt;&lt; &quot;Frisky is &quot; &lt;&lt; Frisky-&gt;GetAge() &lt;&lt; &quot; years old\n&quot;;40:              delete Frisky;41:       return 0;<TT>42: }</TT></FONT><FONT COLOR="#0066FF">Output: Frisky is 2 years oldFrisky is 5 years old</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The class <TT>SimpleCat</TT>is declared to have two member variables--both of which are pointers to integers--onlines 14 and 15. The constructor (lines 22-26) initializes the pointers to memoryon the free store and to the default values.<BR>The destructor (lines 28-32) cleans up the allocated memory. Because this is thedestructor, there is no point in assigning these pointers to <TT>null</TT>, as theywill no longer be accessible. This is one of the safe places to break the rule thatdeleted pointers should be assigned to <TT>null</TT>, although following the ruledoesn't hurt.</P><P>The calling function (in this case, <TT>main()</TT>) is unaware that <TT>itsAge</TT>and <TT>itsWeight</TT> are point-ers to memory on the free store. <TT>main()</TT>continues to call <TT>GetAge()</TT> and <TT>SetAge()</TT>, and the details of thememory management are hidden in the implementation of the class--as they should be.</P><P>When <TT>Frisky</TT> is deleted in line 40, its destructor is called. The destructordeletes each of its member pointers. If these, in turn, point to objects of otheruser-defined classes, their destructors are called as well.<H3 ALIGN="CENTER"><A NAME="Heading36"></A><FONT COLOR="#000077">The this Pointer</FONT></H3><P>Every class member function has a hidden parameter: the <TT>this</TT> pointer.<TT>this</TT> points to the individual object. Therefore, in each call to <TT>GetAge()</TT>or <TT>SetAge()</TT>, the <TT>this</TT> pointer for the object is included as a hiddenparameter.</P><P>It is possible to use the <TT>this</TT> pointer explicitly, as Listing 8.8 illustrates.</P><P><A NAME="Heading37"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.8. Using thethis pointer.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:      // Listing 8.82:      // Using the this pointer3:4:      #include &lt;iostream.h&gt;5:6:      class Rectangle7:      {8:      public:9:           Rectangle();10:           ~Rectangle();11:           void SetLength(int length) { this-&gt;itsLength = length; }12:           int GetLength() const { return this-&gt;itsLength; }13:14:           void SetWidth(int width) { itsWidth = width; }15:           int GetWidth() const { return itsWidth; }16:17:      private:18:           int itsLength;19:           int itsWidth;20:      };21:22:      Rectangle::Rectangle()23:      {24:          itsWidth = 5;25:          itsLength = 10;26:      }27:      Rectangle::~Rectangle()28:      {}29:30:      int main()31:      {32:           Rectangle theRect;33:           cout &lt;&lt; &quot;theRect is &quot; &lt;&lt; theRect.GetLength() &lt;&lt; &quot; feet long.\n&quot;;34:           cout &lt;&lt; &quot;theRect is &quot; &lt;&lt; theRect.GetWidth() &lt;&lt; &quot; feet wide.\n&quot;;35:           theRect.SetLength(20);36:           theRect.SetWidth(10);37:           cout &lt;&lt; &quot;theRect is &quot; &lt;&lt; theRect.GetLength()&lt;&lt; &quot; feet long.\n&quot;;38:           cout &lt;&lt; &quot;theRect is &quot; &lt;&lt; theRect.GetWidth()&lt;&lt; &quot; feet wide.\n&quot;;39:      return 0;<TT>40: }</TT></FONT><FONT COLOR="#0066FF">Output: theRect is 10 feet long.theRect is 5 feet long.theRect is 20 feet long.theRect is 10 feet long.</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis: </B></FONT>The <TT>SetLength()</TT> and <TT>GetLength()</TT>accessor functions explicitly use the <TT>this</TT> pointer to access the membervariables of the <TT>Rectangle</TT> object. The <TT>SetWidth</TT> and <TT>GetWidth</TT>accessors do not. There is no difference in their behavior, although the syntax iseasier to understand.<BR>If that were all there was to the <TT>this</TT> pointer, there would be little pointin bothering you with it. The <TT>this</TT> pointer, however, is a pointer; it storesthe memory address of an object. As such, it can be a powerful tool.</P><P>You'll see a practical use for the <TT>this</TT> pointer on Day 10, &quot;AdvancedFunctions,&quot; when operator overloading is discussed. For now, your goal is toknow about the <TT>this</TT> pointer and to understand what it is: a pointer to theobject itself.</P><P>You don't have to worry about creating or deleting the <TT>this</TT> pointer.The compiler takes care of that.<H3 ALIGN="CENTER"><A NAME="Heading39"></A><FONT COLOR="#000077">Stray or DanglingPointers</FONT></H3><P>One source of bugs that are nasty and difficult to find is stray pointers. A straypointer is created when you call <TT>delete</TT> on a pointer--thereby freeing thememory that it points to--and later try to use that pointer again without reassigningit.</P><P>It is as though the Acme Mail Order company moved away, and you still pressedthe programmed button on your phone. It is possible that nothing terrible happens--atelephone rings in a deserted warehouse. Perhaps the telephone number has been reassignedto a munitions factory, and your call detonates an explosive and blows up your wholecity!</P><P>In short, be careful not to use a pointer after you have called <TT>delete</TT>on it. The pointer still points to the old area of memory, but the compiler is freeto put other data there; using the pointer can cause your program to crash. Worse,your program might proceed merrily on its way and crash several minutes later. Thisis called a time bomb, and it is no fun. To be safe, after you delete a pointer,set it to <TT>null</TT> (<TT>0</TT>). This disarms the pointer.<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Stray pointers are often called	wild pointers or dangling pointers. <HR></BLOCKQUOTE><P>Listing 8.9 illustrates creating a stray pointer.<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>WARNING:</B></FONT><B> </B>This program intentionally creates	a stray pointer. Do NOT run this program--it will crash, if you are lucky. <HR></BLOCKQUOTE><P><A NAME="Heading40"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.9. Creatinga stray pointer.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 8.92:     // Demonstrates a stray pointer3:     typedef unsigned short int USHORT;4:     #include &lt;iostream.h&gt;5:6:     int main()7:     {8:        USHORT * pInt = new USHORT;9:        *pInt = 10;10:       cout &lt;&lt; &quot;*pInt: &quot; &lt;&lt; *pInt &lt;&lt; endl;11:       delete pInt;12:       pInt = 0;13:       long * pLong = new long;14:       *pLong = 90000;15:       cout &lt;&lt; &quot;*pLong: &quot; &lt;&lt; *pLong &lt;&lt; endl;16:17:       *pInt = 20;      // uh oh, this was deleted!18:19:       cout &lt;&lt; &quot;*pInt: &quot; &lt;&lt; *pInt  &lt;&lt; endl;20:       cout &lt;&lt; &quot;*pLong: &quot; &lt;&lt; *pLong  &lt;&lt; endl;21:       delete pLong;22:    return 0;<TT>23: }</TT></FONT><FONT COLOR="#0066FF">Output: *pInt:   10*pLong:  90000*pInt:   20*pLong:  65556Null pointer assignment</FONT></PRE><P>(Your output may look different.)</P><P><FONT COLOR="#000077"><B>Analysis: </B></FONT>Line 8 declares <TT>pInt</TT> tobe a pointer to <TT>USHORT</TT>, and <TT>pInt</TT> is pointed to newly allocatedmemory. Line 9 puts the value <TT>10</TT> in that memory, and line 10 prints itsvalue. After the value is printed, <TT>delete</TT> is called on the pointer. <TT>pInt</TT>is now a stray, or dangling, pointer.<BR>Line 13 declares a new pointer, <TT>pLong</TT>, which is pointed at the memory allocatedby <TT>new</TT>. <BR><BR>Line 14 assigns the value <TT>90000</TT> to <TT>pLong</TT>, and line 15 prints itsvalue.</P><P>Line 17 assigns the value <TT>20</TT> to the memory that <TT>pInt</TT> pointsto, but <TT>pInt</TT> no longer points anywhere that is valid. The memory that <TT>pInt</TT>points to was freed by the call to <TT>delete</TT>, so assigning a value to thatmemory is certain disaster.</P><P>Line 19 prints the value at <TT>pInt</TT>. Sure enough, it is <TT>20</TT>. Line20 prints <TT>20</TT>, the value at <TT>pLong</TT>; it has suddenly been changedto <TT>65556</TT>. Two questions arise:<BR><BR><B>1.</B> How could <TT>pLong</TT>'s value change, given that <TT>pLong</TT> wasn'ttouched?<BR><BR><B>2</B>. Where did the 20 go when <TT>pInt</TT> was used in line 17?<BR><BR>As you might guess, these are related questions. When a value was placed at <TT>pInt</TT>in line 17, the compiler happily placed the value <TT>20</TT> at the memory locationthat <TT>pInt</TT> previously pointed to. However, because that memory was freedin line 11, the compiler was free to reassign it. When <TT>pLong</TT> was createdin line 13, it was given <TT>pInt</TT>'s old memory location. (On some computersthis may not happen, depending on where in memory these values are stored.) Whenthe value <TT>20</TT> was assigned to the location that <TT>pInt</TT> previouslypointed to, it wrote over the value pointed to by <TT>pLong</TT>. This is called&quot;stomping on a pointer.&quot; It is often the unfortunate outcome of using a

⌨️ 快捷键说明

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