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

📄 ch10.htm

📁 一本好的VC学习书,本人就是使用这本书开始学习的vc,希望能对大家有帮助
💻 HTM
📖 第 1 页 / 共 5 页
字号:
46:  {47:       CAT frisky;48:       cout &lt;&lt; &quot;frisky's age: &quot; &lt;&lt; frisky.GetAge() &lt;&lt; endl;49:       cout &lt;&lt; &quot;Setting frisky to 6...\n&quot;;50:       frisky.SetAge(6);51:       cout &lt;&lt; &quot;Creating boots from frisky\n&quot;;52:       CAT boots(frisky);53:       cout &lt;&lt; &quot;frisky's age: &quot; &lt;&lt;     frisky.GetAge() &lt;&lt; endl;54:       cout &lt;&lt; &quot;boots' age: &quot; &lt;&lt; boots.GetAge() &lt;&lt; endl;55:       cout &lt;&lt; &quot;setting frisky to 7...\n&quot;;56:       frisky.SetAge(7);57:       cout &lt;&lt; &quot;frisky's age: &quot; &lt;&lt;     frisky.GetAge() &lt;&lt; endl;58:       cout &lt;&lt; &quot;boot's age: &quot; &lt;&lt; boots.GetAge() &lt;&lt; endl;59:     return 0;<TT>60: }</TT></FONT><FONT COLOR="#0066FF">Output: frisky's age: 5Setting frisky to 6...Creating boots from friskyfrisky's age: 6boots' age:  6setting frisky to 7...frisky's age: 7boots' age: 6</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On lines 6-19, the <TT>CAT</TT>class is declared. Note that on line 9 a default constructor is declared, and online 10 a copy constructor is declared.<BR>On lines 17 and 18, two member variables are declared, each as a pointer to an integer.Typically there'd be little reason for a class to store <TT>int</TT> member variablesas pointers, but this was done to illustrate how to manage member variables on thefree store.</P><P>The default constructor, on lines 21-27, allocates room on the free store fortwo <TT>int</TT> variables and then assigns values to them.</P><P>The copy constructor begins on line 29. Note that the parameter is <TT>rhs</TT>.It is common to refer to the parameter to a copy constructor as <TT>rhs</TT>, whichstands for right-hand side. When you look at the assignments in lines 33 and 34,you'll see that the object passed in as a parameter is on the right-hand side ofthe equals sign. Here's how it works.</P><P>On lines 31 and 32, memory is allocated on the free store. Then, on lines 33 and34, the value at the new memory location is assigned the values from the existing<TT>CAT</TT>.</P><P>The parameter <TT>rhs</TT> is a <TT>CAT</TT> that is passed into the copy constructoras a constant reference. The member function <TT>rhs.GetAge()</TT> returns the valuestored in the memory pointed to by <TT>rhs</TT>'s member variable <TT>itsAge</TT>.As a <TT>CAT</TT> object, <TT>rhs</TT> has all the member variables of any other<TT>CAT</TT>.</P><P>When the copy constructor is called to create a new <TT>CAT</TT>, an existing<TT>CAT</TT> is passed in as a parameter. The new <TT>CAT</TT> can refer to its ownmember variables directly; however, it must access <TT>rhs</TT>'s member variablesusing the public accessor methods.</P><P>Figure 10.3 diagrams what is happening here. The values pointed to by the existing<TT>CAT</TT> are copied to the memory allocated for the new <TT>CAT</TT><BR><BR><A NAME="Heading22"></A><A HREF="102cp03.jpg" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/art/ch10/102cp03.jpg"><FONT COLOR="#000077">Figure10.3.</FONT></A><FONT COLOR="#000077"> </FONT><I>Deep copy illustrated.</I><BR><BR>On line 47, a <TT>CAT</TT> called <TT>frisky</TT> is created. <TT>frisky</TT>'s ageis printed, and then his age is set to 6 on line 50. On line 52, a new <TT>CAT</TT><TT>boots</TT> is created, using the copy constructor and passing in <TT>frisky</TT>.Had <TT>frisky</TT> been passed as a parameter to a function, this same call to thecopy constructor would have been made by the compiler.<BR><BR>On lines 53 and 54, the ages of both <TT>CAT</TT>s are printed. Sure enough, <TT>boots</TT>has <TT>frisky</TT>'s age, <TT>6</TT>, not the default age of <TT>5</TT>. On line56, <TT>frisky</TT>'s age is set to <TT>7</TT>, and then the ages are printed again.This time <TT>frisky</TT>'s age is <TT>7</TT>, but <TT>boots</TT>' age is still <TT>6</TT>,demonstrating that they are stored in separate areas of memory.</P><P>When the <TT>CAT</TT>s fall out of scope, their destructors are automaticallyinvoked. The implementation of the <TT>CAT</TT> destructor is shown on lines 37-43.<TT>delete</TT> is called on both pointers, <TT>itsAge</TT> and <TT>itsWeight</TT>,returning the allocated memory to the free store. Also, for safety, the pointersare reassigned to <TT>NULL</TT>.<H4 ALIGN="CENTER"><A NAME="Heading23"></A><FONT COLOR="#000077">Operator Overloading</FONT></H4><P>C++ has a number of built-in types, including <TT>int</TT>, <TT>real</TT>, <TT>char</TT>,and so forth. Each of these has a number of built-in operators, such as addition(<TT>+</TT>) and multiplication (<TT>*</TT>). C++ enables you to add these operatorsto your own classes as well.</P><P>In order to explore operator overloading fully, Listing 10.6 creates a new class,<TT>Counter</TT>. A <TT>Counter</TT> object will be used in counting (surprise!)in loops and other applications where a number must be incremented, decremented,or otherwise tracked.</P><P><A NAME="Heading24"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 10.6. The Counterclass.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 10.62:     // The Counter class3:4:     typedef unsigned short  USHORT;5:     #include &lt;iostream.h&gt;6:7:     class Counter8:     {9:        public:10:          Counter();11:          ~Counter(){}12:          USHORT GetItsVal()const { return itsVal; }13:          void SetItsVal(USHORT x) {itsVal = x; }14:15:       private:16:          USHORT itsVal;17:18:    };19:20:    Counter::Counter():21:    itsVal(0)22:    {};23:24:    int main()25:    {26:       Counter i;27:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;28:     return 0;<TT>29: }</TT>Output: The value of i is 0</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>As it stands, this is a prettyuseless class. It is defined on lines 7-18. Its only member variable is a <TT>USHORT</TT>.The default constructor, which is declared on line 10 and whose implementation ison line 20, initializes the one member variable, <TT>itsVal</TT>, to zero.<BR><BR>Unlike an honest, red-blooded <TT>USHORT</TT>, the <TT>Counter</TT> object cannotbe incremented, decremented, added, assigned, or otherwise manipulated. In exchangefor this, it makes printing its value far more difficult!<H4 ALIGN="CENTER"><A NAME="Heading26"></A><FONT COLOR="#000077">Writing an IncrementFunction</FONT></H4><P>Operator overloading restores much of the functionality that has been strippedout of this class. For example, there are two ways to add the ability to incrementa <TT>Counter</TT> object. The first is to write an increment method, as shown inListing 10.7.</P><P><A NAME="Heading27"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 10.7. Addingan increment operator.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 10.72:     // The Counter class3:4:     typedef unsigned short  USHORT;5:     #include &lt;iostream.h&gt;6:7:     class Counter8:     {9:        public:10:          Counter();11:          ~Counter(){}12:          USHORT GetItsVal()const { return itsVal; }13:          void SetItsVal(USHORT x) {itsVal = x; }14:          void Increment() { ++itsVal; }15:16:       private:17:          USHORT itsVal;18:19:    };20:21:    Counter::Counter():22:    itsVal(0)23:    {};24:25:    int main()26:    {27:       Counter i;28:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;29:       i.Increment();30:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;31:     return 0;<TT>32: }</TT></FONT></PRE><PRE><FONT COLOR="#0066FF">Output: The value of i is 0The value of i is 1</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 10.7 adds an <TT>Increment</TT>function, defined on line 14. Although this works, it is cumbersome to use. The programcries out for the ability to add a <TT>++</TT> operator, and of course this can bedone.<H4 ALIGN="CENTER"><A NAME="Heading29"></A><FONT COLOR="#000077">Overloading thePrefix Operator</FONT></H4><P>Prefix operators can be overloaded by declaring functions with the form:</P><PRE><FONT COLOR="#0066FF">returnType Operator op (parameters)</FONT></PRE><P>Here, <TT>op</TT> is the operator to overload. Thus, the <TT>++</TT> operatorcan be overloaded with the following syntax:</P><PRE><FONT COLOR="#0066FF">void operator++ ()</FONT></PRE><P>Listing 10.8 demonstrates this alternative.</P><P><A NAME="Heading30"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 10.8. Overloadingoperator++.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 10.82:     // The Counter class3:4:     typedef unsigned short  USHORT;5:     #include &lt;iostream.h&gt;6:7:     class Counter8:     {9:        public:10:          Counter();11:          ~Counter(){}12:          USHORT GetItsVal()const { return itsVal; }13:          void SetItsVal(USHORT x) {itsVal = x; }14:          void Increment() { ++itsVal; }15:          void operator++ () { ++itsVal; }16:17:       private:18:          USHORT itsVal;19:20:    };21:22:    Counter::Counter():23:    itsVal(0)24:    {};25:26:    int main()27:    {28:       Counter i;29:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;30:       i.Increment();31:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;32:       ++i;33:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;34:     return 0;<TT>35: }</TT>Output: The value of i is 0The value of i is 1The value of i is 2</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On line 15, <TT>operator++</TT>is overloaded, and it's used on line 32. This is far closer to the syntax one wouldexpect with the <TT>Counter</TT> object. At this point, you might consider puttingin the extra abilities for which <TT>Counter</TT> was created in the first place,such as detecting when the <TT>Counter</TT> overruns its maximum size.<BR>There is a significant defect in the way the increment operator was written, however.If you want to put the <TT>Counter</TT> on the right side of an assignment, it willfail. For example:</P><PRE><FONT COLOR="#0066FF">Counter a = ++i;</FONT></PRE><P>This code intends to create a new <TT>Counter</TT>, <TT>a</TT>, and then assignto it the value in <TT>i</TT> after <TT>i</TT> is incremented. The built-in copyconstructor will handle the assignment, but the current increment operator does notreturn a <TT>Counter</TT> object. It returns <TT>void</TT>. You can't assign a <TT>void</TT>object to a <TT>Counter</TT> object. (You can't make something from nothing!)<H4 ALIGN="CENTER"><A NAME="Heading32"></A><FONT COLOR="#000077">Returning Typesin Overloaded Operator Functions</FONT></H4><P>Clearly, what you want is to return a <TT>Counter</TT> object so that it can beassigned to another <TT>Counter</TT> object. Which object should be returned? Oneapproach would be to create a temporary object and return that. Listing 10.9 illustratesthis approach.</P><P><A NAME="Heading33"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 10.9. Returninga temporary object.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 10.92:     // operator++ returns a temporary object3:4:     typedef unsigned short  USHORT;5:     #include &lt;iostream.h&gt;6:7:     class Counter8:     {9:        public:10:          Counter();11:          ~Counter(){}12:          USHORT GetItsVal()const { return itsVal; }13:          void SetItsVal(USHORT x) {itsVal = x; }14:          void Increment() { ++itsVal; }15:          Counter operator++ ();16:17:       private:18:          USHORT itsVal;19:20:    };21:22:    Counter::Counter():23:    itsVal(0)24:    {};25:26:    Counter Counter::operator++()27:    {28:        ++itsVal;29:        Counter temp;30:        temp.SetItsVal(itsVal);31:        return temp;32:    }33:34:    int main()35:    {36:       Counter i;37:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;38:       i.Increment();39:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;40:       ++i;41:       cout &lt;&lt; &quot;The value of i is &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;42:       Counter a = ++i;43:       cout &lt;&lt; &quot;The value of a: &quot; &lt;&lt; a.GetItsVal();44:       cout &lt;&lt; &quot; and i: &quot; &lt;&lt; i.GetItsVal() &lt;&lt; endl;45:     return 0;<TT>46: }</TT></FONT><FONT COLOR="#0066FF">Output: The value of i is 0The value of i is 1The value of i is 2The value of a: 3 and i: 3</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>In this version, <TT>operator++</TT>has been declared on line 15 to return a <TT>Counter</TT> object. On line 29, a temporaryvariable, <TT>temp</TT>, is created and its value is set to match that in the currentobject. That temporary variable is returned and immediately assigned to <TT>a</TT>on line 42.

⌨️ 快捷键说明

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