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

📄 ch15.htm

📁 一本好的VC学习书,本人就是使用这本书开始学习的vc,希望能对大家有帮助
💻 HTM
📖 第 1 页 / 共 5 页
字号:
74:       Edie.SetFirstName(&quot;Edythe&quot;);75:76:       cout &lt;&lt; &quot;Name: &quot;;77:       cout &lt;&lt; Edie.GetFirstName().GetString();78:       cout &lt;&lt; &quot; &quot; &lt;&lt; Edie.GetLastName().GetString();79:       cout &lt;&lt; &quot;.\nAddress: &quot;;80:       cout &lt;&lt; Edie.GetAddress().GetString();81:       cout &lt;&lt; &quot;.\nSalary: &quot; ;82:       cout &lt;&lt; Edie.GetSalary();83:     return 0;<TT>84: }</TT></FONT></PRE><BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE: </B></FONT>Put the code from Listing 15.1 into a file	called <TT>STRING.HPP</TT>. Then any time you need the <TT>String</TT> class you	can include Listing 15.1 by using <TT>#include</TT>. For example, at the top of Listing	15.2 add the line <TT>#include String.hpp</TT>. This will add the <TT>String</TT>	class to your program. <HR></BLOCKQUOTE><PRE><FONT COLOR="#0066FF">Output: Name: Edythe Levine.Address: 1461 Shore Parkway.Salary: 50000</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 15.2 shows the <TT>Employee</TT>class, which contains three string objects: <TT>itsFirstName</TT>,<TT> itsLastName</TT>,and <TT>itsAddress</TT>.</P><P>On line 70, an <TT>Employee</TT> object is created, and four values are passedin to initialize the <TT>Employee</TT> object. On line 71, the <TT>Employee</TT>access function <TT>SetSalary()</TT> is called, with the constant value <TT>50000</TT>.Note that in a real program this would either be a dynamic value (set at runtime)or a constant.</P><P>On line 72, a string is created and initialized using a C++ string constant. Thisstring object is then used as an argument to <TT>SetLastName()</TT> on line 73.</P><P>On line 74, the <TT>Employee</TT> function <TT>SetFirstName()</TT> is called withyet another string constant. However, if you are paying close attention, you willnotice that <TT>Employee</TT> does not have a function <TT>SetFirstName()</TT> thattakes a character string as its argument; <TT>SetFirstName()</TT> requires a constantstring reference.</P><P>The compiler resolves this because it knows how to make a string from a constantcharacter string. It knows this because you told it how to do so on line 9 of Listing15.1.<H4 ALIGN="CENTER"><A NAME="Heading8"></A><FONT COLOR="#000077">Accessing Membersof the Contained Class</FONT></H4><P><TT>Employee</TT> objects do not have special access to the member variables of<TT>String</TT>. If the <TT>Employee</TT> object <TT>Edie</TT> tried to access themember variable <TT>itsLen</TT> of its own <TT>itsFirstName</TT> member variable,it would get a compile-time error. This is not much of a burden, however. The accessorfunctions provide an interface for the <TT>String</TT> class, and the <TT>Employee</TT>class need not worry about the implementation details, any more than it worries abouthow the integer variable, <TT>itsSalary</TT>, stores its information.<H4 ALIGN="CENTER"><A NAME="Heading9"></A><FONT COLOR="#000077">Filtering Accessto Contained Members</FONT></H4><P>Note that the <TT>String</TT> class provides the <TT>operator+</TT>. The designerof the <TT>Employee</TT> class has blocked access to the <TT>operator+</TT> beingcalled on <TT>Employee</TT> objects by declaring that all the string accessors, suchas <TT>GetFirstName()</TT>, return a constant reference. Because <TT>operator+</TT>is not (and can't be) a <TT>const</TT> function (it changes the object it is calledon), attempting to write the following will cause a compile-time error:</P><PRE><FONT COLOR="#0066FF">String buffer = Edie.GetFirstName() + Edie.GetLastName();</FONT></PRE><P><TT>GetFirstName()</TT> returns a constant <TT>String</TT>, and you can't call<TT>operator+</TT> on a constant object.</P><P>To fix this, overload <TT>GetFirstName()</TT> to be non-<TT>const</TT>:</P><PRE><FONT COLOR="#0066FF">const String &amp; GetFirstName() const { return itsFirstName; }String &amp; GetFirstName()  { return itsFirstName; }</FONT></PRE><P>Note that the return value is no longer <TT>const</TT> and that the member functionitself is no longer <TT>const</TT>. Changing the return value is not sufficient tooverload the function name; you must change the constancy of the function itself.<H4 ALIGN="CENTER"><A NAME="Heading10"></A><FONT COLOR="#000077">Cost of Containment</FONT></H4><P>It is important to note that the user of an <TT>Employee</TT> class pays the priceof each of those string objects each time one is constructed, or a copy of the <TT>Employee</TT>is made.</P><P>Uncommenting the <TT>cout</TT> statements in Listing 15.1, lines 38, 51, 63, 75,84, and 100, reveals how often these are called. Listing 15.3 rewrites the driverprogram to add <TT>print</TT> statements indicating where in the program objectsare being created:<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE: </B></FONT>To compile this listing, follow these steps:	1. Uncomment lines 38, 51, 63, 75, 84, and 100 in Listing 15.1. 2. Edit Listing 15.2.	Remove lines 64-80 and substitute Listing 15.3. 3. Add <TT>#include string.hpp</TT>	as previously noted. <HR></BLOCKQUOTE><P><A NAME="Heading11"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 15.3. Containedclass constructors.</B></FONT><PRE><FONT COLOR="#0066FF">1:     int main()2:     {3:        cout &lt;&lt; &quot;Creating Edie...\n&quot;;4:        Employee Edie(&quot;Jane&quot;,&quot;Doe&quot;,&quot;1461 Shore Parkway&quot;, 20000);5:        Edie.SetSalary(20000);6:        cout &lt;&lt; &quot;Calling SetFirstName with char *...\n&quot;;7:        Edie.SetFirstName(&quot;Edythe&quot;);8:        cout &lt;&lt; &quot;Creating temporary string LastName...\n&quot;;9:        String LastName(&quot;Levine&quot;);10:       Edie.SetLastName(LastName);11:12:       cout &lt;&lt; &quot;Name: &quot;;13:       cout &lt;&lt; Edie.GetFirstName().GetString();14:       cout &lt;&lt; &quot; &quot; &lt;&lt; Edie.GetLastName().GetString();15:       cout &lt;&lt; &quot;\nAddress: &quot;;16:       cout &lt;&lt; Edie.GetAddress().GetString();17:       cout &lt;&lt; &quot;\nSalary: &quot; ;18:       cout &lt;&lt; Edie.GetSalary();19:       cout &lt;&lt; endl;20:     return 0;<TT>21: }</TT></FONT><FONT COLOR="#0066FF">Output: 1:   Creating Edie...2:           String(char*) constructor3:           String(char*) constructor4:           String(char*) constructor5:   Calling SetFirstName with char *...6:           String(char*) constructor7:           String destructor8:   Creating temporary string LstName...9:           String(char*) constructor10:  Name: Edythe Levine11:  Address: 1461 Shore Parkway12:  Salary: 2000013:          String destructor14:          String destructor15:          String destructor16:          String destructor</FONT></PRE><P><B>Analysis: </B>Listing 15.3 uses the same class declarations as Listings 15.1and 15.2. However, the <TT>cout</TT> statements have been uncommented. The outputfrom Listing 15.3 has been numbered to make analysis easier.</P><P>On line 3 of Listing 15.3, the statement <TT>Creating Edie...</TT> is printed,as reflected on line 1 of the output. On line 4 an <TT>Employee</TT> object, <TT>Edie</TT>,is created with four parameters. The output reflects the constructor for <TT>String</TT>being called three times, as expected.</P><P>Line 6 prints an information statement, and then on line 7 is the statement <TT>Edie.SetFirstName(&quot;Edythe&quot;)</TT>.This statement causes a temporary string to be created from the character string<TT>&quot;Edythe&quot;</TT>, as reflected on lines 6 and 7 of the output. Note thatthe temporary is destroyed immediately after it is used in the assignment statement.</P><P>On line 9, a <TT>String</TT> object is created in the body of the program. Herethe programmer is doing explicitly what the compiler did implicitly on the previousstatement. This time you see the constructor on line 9 of the output, but no destructor.This object will not be destroyed until it goes out of scope at the end of the function.</P><P>On lines 13-19, the strings in the employee object are destroyed as the <TT>Employee</TT>object falls out of scope, and the string <TT>LastName</TT>, created on line 9, isdestroyed as well when it falls out of scope.<H4 ALIGN="CENTER"><A NAME="Heading13"></A><FONT COLOR="#000077">Copying by Value</FONT></H4><P>Listing 15.3 illustrates how the creation of one <TT>Employee</TT> object causedfive string constructor calls. Listing 15.4 again rewrites the driver program. Thistime the <TT>print</TT> statements are not used, but the string static member variable<TT>ConstructorCount</TT> is uncommented and used.</P><P>Examination of Listing 15.1 shows that <TT>ConstructorCount</TT> is incrementedeach time a string constructor is called. The driver program in 15.4 calls the <TT>print</TT>functions, passing in the <TT>Employee</TT> object, first by reference and then byvalue. <TT>ConstructorCount</TT> keeps track of how many string objects are createdwhen the employee is passed as a parameter.<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To compile this listing: 1. Uncomment	lines 23, 39, 52, 64, 76, and 152 in Listing 15.1. 2. Edit Listing 15.2. Remove lines	68-84 and substitute Listing 15.4. 3. Add <TT>#include string.hpp</TT> as previously	noted. <HR></BLOCKQUOTE><P><A NAME="Heading14"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 15.4. Passingby value</B></FONT><PRE><FONT COLOR="#0066FF">1:     void PrintFunc(Employee);2:     void rPrintFunc(const Employee&amp;);3:4:     int main()5:     {6:        Employee Edie(&quot;Jane&quot;,&quot;Doe&quot;,&quot;1461 Shore Parkway&quot;, 20000);7:        Edie.SetSalary(20000);8:        Edie.SetFirstName(&quot;Edythe&quot;);9:        String LastName(&quot;Levine&quot;);10:       Edie.SetLastName(LastName);11:12:       cout &lt;&lt; &quot;Constructor count: &quot; ;13:       cout &lt;&lt; String::ConstructorCount &lt;&lt; endl;14:       rPrintFunc(Edie);15:       cout &lt;&lt; &quot;Constructor count: &quot;;16:        cout &lt;&lt; String::ConstructorCount &lt;&lt; endl;17:       PrintFunc(Edie);18:       cout &lt;&lt; &quot;Constructor count: &quot;;19:        cout &lt;&lt; String::ConstructorCount &lt;&lt; endl;20:     return 0;21:    }22:    void PrintFunc (Employee Edie)23:    {24:25:       cout &lt;&lt; &quot;Name: &quot;;26:       cout &lt;&lt; Edie.GetFirstName().GetString();27:       cout &lt;&lt; &quot; &quot; &lt;&lt; Edie.GetLastName().GetString();28:       cout &lt;&lt; &quot;.\nAddress: &quot;;29:       cout &lt;&lt; Edie.GetAddress().GetString();30:       cout &lt;&lt; &quot;.\nSalary: &quot; ;31:       cout &lt;&lt; Edie.GetSalary();32:       cout &lt;&lt; endl;33:34:    }35:36:    void rPrintFunc (const Employee&amp; Edie)37:    {38:       cout &lt;&lt; &quot;Name: &quot;;39:       cout &lt;&lt; Edie.GetFirstName().GetString();40:       cout &lt;&lt; &quot; &quot; &lt;&lt; Edie.GetLastName().GetString();41:       cout &lt;&lt; &quot;\nAddress: &quot;;42:       cout &lt;&lt; Edie.GetAddress().GetString();43:       cout &lt;&lt; &quot;\nSalary: &quot; ;44:       cout &lt;&lt; Edie.GetSalary();45:       cout &lt;&lt; endl;<TT>46: }</TT>Output: String(char*) constructor        String(char*) constructor        String(char*) constructor        String(char*) constructor        String destructor        String(char*) constructorConstructor count: 5Name: Edythe LevineAddress: 1461 Shore ParkwaySalary: 20000Constructor count: 5        String(String&amp;) constructor        String(String&amp;) constructor        String(String&amp;) constructorName: Edythe Levine.Address: 1461 Shore Parkway.Salary: 20000        String destructor        String destructor        String destructorConstructor count: 8String destructor        String destructor        String destructor        String destructor</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The output shows that fivestring objects were created as part of creating one <TT>Employee</TT> object. Whenthe <TT>Employee</TT> object is passed to <TT>rPrintFunc()</TT> by reference, noadditional <TT>Employee</TT> objects are created, and so no additional <TT>String</TT>objects are created. (They too are passed by reference.)</P><P>When, on line 14, the <TT>Employee</TT> object is passed to <TT>PrintFunc()</TT>by value, a copy of the <TT>Employee</TT> is created, and three more string objectsare created (by calls to the copy constructor).<H3 ALIGN="CENTER"><A NAME="Heading16"></A><FONT COLOR="#000077">Implementation inTerms of Inheritance/Containment Versus Delegation</FONT></H3><P>At times, one class wants to draw on some of the attributes of another class.For example, let's say you need to create a <TT>PartsCatalog</TT> class. The specificationyou've been given defines a <TT>PartsCatalog</TT> as a collection of parts; eachpart has a unique part number. The <TT>PartsCatalog</TT> does not allow duplicateentries, and does allow access by part number.</P><P>The listing for the Week in Review for Week 2 provides a <TT>LinkedList</TT> class.This <TT>LinkedList</TT> is well-tested and understood, and you'd like to build onthat technology when making your <TT>PartsCatalog</TT>, rather than inventing itfrom scratch.</P><P>You could create a new <TT>PartsCatalog</TT> class and have it contain a <TT>LinkedList</TT>.The <TT>PartsCatalog</TT> could delegate management of the linked list to its contained<TT>LinkedList</TT> object.</P><P>An alternative would be to make the <TT>PartsCatalog</TT> derive from <TT>LinkedList</TT>and thereby inherit the properties of a <TT>LinkedList</TT>. Remembering, however,that public inheritance provides an is-a relationship, you should question whethera <TT>PartsCatalog</TT> really is a type of <TT>LinkedList</TT>.</P><P>One way to answer the question of whether <TT>PartsCatalog</TT> is a <TT>LinkedList</TT>is to assume that <TT>LinkedList</TT> is the base and <TT>PartsCatalog</TT> is thederived class, and then to ask these other questions:<DL>	<DD><B>1.</B> Is there anything in the base class that should not be in the derived?	For example, does the <TT>LinkedList</TT> base class have functions that are inappropriate	for the <TT>PartsCatalog</TT> <BR>	class? If so, you probably don't want public inheritance.<BR>	<BR>	<B>2.</B> Might the class you are creating have more than one of the base? For example,	might a <TT>PartsCatalog</TT> need two <TT>LinkedList</TT>s in each object? If it	might, you almost certainly want to use containment.<BR>	<BR>	<B>3.</B> Do you need to inherit from the base class so that you can take advantage	of virtual functions or access protected members? If so, you must use inheritance,	public or private.</DL><P>Based on the answers to these questions, you must chose between public inheritance(the is-a relationship) and either private inheritance or containment.<DL>	<DD><HR><FONT COLOR="#000077"><B>New Term:</B></FONT>	<UL>		<P>	</UL>	<DD><B>Contained --</B>An object declared as a member of another class contained	by that class.<BR>	<BR>	<B>Delegation -</B>-Using the attributes of a contained class to accomplish functions	not otherwise available to the containing class.<BR>	<BR>	<B>Implemented in terms of --</B>Building one class on the capabilities of another	without using public inheritance. <HR></DL><H4 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">Delegation</FONT></H4><P>Why not derive <TT>PartsCatalog</TT> from <TT>LinkedList</TT>? The <TT>PartsCatalog</TT>isn't a <TT>LinkedList</TT> because <TT>LinkedList</TT>s are ordered collectionsand each member of the collection can repeat. The <TT>PartsCatalog</TT> has uniqueentries that are not ordered. The fifth member of the <TT>PartsCatalog</TT> is notpart number 5.</P><P>Certainly it would have been possible to inherit publicly from <TT>PartsList</TT>and then override <TT>Insert()</TT> and the offset operators (<TT>[]</TT>) to dothe right thing, but then you would have changed the essence of the <TT>PartsList</TT>class. Instead you'll build a <TT>PartsCatalog</TT> that has no offset operator,does not allow duplicates, and defines the <TT>operator+</TT> to combine two sets.</P><P>The first way to accomplish this is with containment. The <TT>PartsCatalog</TT>will delegate list management to a contained <TT>LinkedList</TT>. Listing 15.5 illustratesthis approach.</P><P><A NAME="Heading18"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 15.5. Delegatingto a contained LinkedList.</B></FONT><PRE><FONT COLOR="#0066FF">0:      #include &lt;iostream.h&gt;1:    2:      typedef unsigned long ULONG;

⌨️ 快捷键说明

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