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

📄 ch15.htm

📁 一本好的VC学习书,本人就是使用这本书开始学习的vc,希望能对大家有帮助
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<FONT COLOR="#0066FF">Output: (0)Quit (1)Car (2)Plane:  1New PartNumber?: 1234Model Year?: 94(0)Quit (1)Car (2)Plane:  1New PartNumber?: 4434Model Year?: 93(0)Quit (1)Car (2)Plane:  1New PartNumber?: 1234Model Year?: 941234 was the first entry. Rejected!(0)Quit (1)Car (2)Plane:  1New PartNumber?: 2345Model Year?: 93(0)Quit (1)Car (2)Plane:  0Part Number: 1234Model Year: 94Part Number: 2345Model Year: 93Part Number: 4434Model Year: 93</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 15.7 reproduces theinterface to the <TT>Part</TT>, <TT>PartNode</TT>, and <TT>PartList</TT> classesfrom Week 2 in Review, but to save room it does not reproduce the implementationof their methods.</P><P>A new class, <TT>PartsCatalog</TT>, is declared on lines 260-270. <TT>PartsCatalog</TT>has a <TT>PartsList</TT> as its data member, to which it delegates list management.Another way to say this is that the <TT>PartsCatalog</TT> is implemented in termsof this <TT>PartsList</TT>.</P><P>Note that clients of the <TT>PartsCatalog</TT> do not have access to the <TT>PartsList</TT>directly. The interface is through the <TT>PartsCatalog</TT>, and as such the behaviorof the <TT>PartsList</TT> is dramatically changed. For example, the <TT>PartsCatalog::Insert()</TT>method does not allow duplicate entries into the <TT>PartsList</TT>.</P><P>The implementation of <TT>PartsCatalog::Insert()</TT> starts on line 272. The<TT>Part</TT> that is passed in as a parameter is asked for the value of its <TT>itsPartNumber</TT>member variable. This value is fed to the <TT>PartsList</TT>'s <TT>Find()</TT> method,and if no match is found the number is inserted; otherwise an informative error messageis printed.</P><P>Note that <TT>PartsCatalog</TT> does the actual insert by calling <TT>Insert()</TT>on its member variable, <TT>pl</TT>, which is a <TT>PartsList</TT>. The mechanicsof the actual insertion and the maintenance of the linked list, as well as searchingand retrieving from the linked list, are maintained in the contained <TT>PartsList</TT>member of <TT>PartsCatalog</TT>. There is no reason for <TT>PartsCatalog</TT> toreproduce this code; it can take full advantage of the well-defined interface.</P><P>This is the essence of reusability within C++: <TT>PartsCatalog</TT> can reusethe <TT>PartsList</TT> code, and the designer of <TT>PartsCatalog</TT> is free toignore the implementation details of <TT>PartsList</TT>. The interface to <TT>PartsList</TT>(that is, the class declaration) provides all the information needed by the designerof the <TT>PartsCatalog</TT> class.<H3 ALIGN="CENTER"><A NAME="Heading20"></A><FONT COLOR="#000077">Private Inheritance</FONT></H3><P>If <TT>PartsCatalog</TT> needed access to the protected members of <TT>LinkedList</TT>(in this case there are none), or needed to override any of the <TT>LinkedList</TT>methods, then <TT>PartsCatalog</TT> would be forced to inherit from <TT>PartsList</TT>.</P><P>Since a <TT>PartsCatalog</TT> is not a <TT>PartsList</TT> object, and since youdon't want to expose the entire set of functionality of <TT>PartsList</TT> to clientsof <TT>PartsCatalog</TT>, you need to use private inheritance.</P><P>The first thing to know about private inheritance is that all of the base membervariables and functions are treated as if they were declared to be private, regardlessof their actual access level in the base. Thus, to any function that is not a memberfunction of <TT>PartsCatalog</TT>, every function inherited from <TT>PartsList</TT>is inaccessible. This is critical: private inheritance does not involve inheritinginterface, just implementation.</P><P>To clients of the <TT>PartsCatalog</TT> class, the <TT>PartsList</TT> class isinvisible. None of its interface is available: you can't call any of its methods.You can call <TT>PartsCatalog</TT> methods, however, and they can access all of <TT>LinkedLists</TT>,because they are derived from <TT>LinkedLists</TT>.</P><P>The important thing here is that the <TT>PartsCatalog</TT> isn't a <TT>PartsList</TT>,as would have been implied by public inheritance. It is implemented in terms of a<TT>PartsList</TT>, just as would have been the case with containment. The privateinheritance is just a convenience.</P><P>Listing 15.6 demonstrates the use of private inheritance by rewriting the <TT>PartsCatalog</TT>class as privately derived from <TT>PartsList</TT>.<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To compile this program, replace	lines 260-344 of Listing 15.5 with Listing 15.6 and recompile. <HR></BLOCKQUOTE><P><A NAME="Heading21"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 15.6. Privateinheritance.</B></FONT><PRE><FONT COLOR="#0066FF">1:  //listing 15.6 demonstrates private inheritance2:3:  //rewrites PartsCatalog from listing 15.54:5:  //see attached notes on compiling6:7:     class PartsCatalog : private PartsList8:     {9:     public:10:       void Insert(Part *);11:       ULONG Exists(ULONG PartNumber);12:       Part * Get(int PartNumber);13:       operator+(const PartsCatalog &amp;);14:       void ShowAll() { Iterate(Part::Display); }15:    private:16:    };17:18:    void PartsCatalog::Insert(Part * newPart)19:    {20:       ULONG partNumber =  newPart-&gt;GetPartNumber();21:       ULONG offset;22:23:       if (!Find(offset, partNumber))24:          PartsList::Insert(newPart);25:       else26:       {27:          cout &lt;&lt; partNumber &lt;&lt; &quot; was the &quot;;28:          switch (offset)29:          {30:             case 0:  cout &lt;&lt; &quot;first &quot;; break;31:             case 1:  cout &lt;&lt; &quot;second &quot;; break;32:             case 2:  cout &lt;&lt; &quot;third &quot;; break;33:             default: cout &lt;&lt; offset+1 &lt;&lt; &quot;th &quot;;34:          }35:          cout &lt;&lt; &quot;entry. Rejected!\n&quot;;36:       }37:    }38:39:    ULONG PartsCatalog::Exists(ULONG PartNumber)40:    {41:       ULONG offset;42:       Find(offset,PartNumber);43:       return offset;44:    }45:46:    Part * PartsCatalog::Get(int PartNumber)47:    {48:       ULONG offset;49:       return (Find(offset, PartNumber));50:51:    }52:53:    int main()54:    {55:       PartsCatalog pc;56:       Part * pPart = 0;57:       ULONG PartNumber;58:       USHORT value;59:       ULONG choice;60:61:       while (1)62:       {63:          cout &lt;&lt; &quot;(0)Quit (1)Car (2)Plane: &quot;;64:          cin &gt;&gt; choice;65:66:          if (!choice)67:             break;68:69:          cout &lt;&lt; &quot;New PartNumber?: &quot;;70:          cin &gt;&gt;  PartNumber;71:72:          if (choice == 1)73:          {74:             cout &lt;&lt; &quot;Model Year?: &quot;;75:             cin &gt;&gt; value;76:             pPart = new CarPart(value,PartNumber);77:          }78:          else79:          {80:             cout &lt;&lt; &quot;Engine Number?: &quot;;81:             cin &gt;&gt; value;82:             pPart = new AirPlanePart(value,PartNumber);83:          }84:          pc.Insert(pPart);85:       }86:       pc.ShowAll();87:     return 0;<TT>88: }</TT></FONT><FONT COLOR="#0066FF">Output: (0)Quit (1)Car (2)Plane:  1New PartNumber?: 1234Model Year?: 94(0)Quit (1)Car (2)Plane:  1New PartNumber?: 4434Model Year?: 93(0)Quit (1)Car (2)Plane:  1New PartNumber?: 1234Model Year?: 941234 was the first entry. Rejected!(0)Quit (1)Car (2)Plane:  1New PartNumber?: 2345Model Year?: 93(0)Quit (1)Car (2)Plane:  0Part Number: 1234Model Year: 94Part Number: 2345Model Year: 93Part Number: 4434Model Year: 93</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 15.6 shows only thechanged interface to <TT>PartsCatalog</TT> and the rewritten driver program. Theinterfaces to the other classes are unchanged from Listing 15.5.</P><P>On line 7 of Listing 15.6, <TT>PartsCatalog</TT> is declared to derive privatelyfrom <TT>PartsList</TT>. The interface to <TT>PartsCatalog</TT> doesn't change fromListing 15.5, though of course it no longer needs an object of type <TT>PartsList</TT>as member data.</P><P>The <TT>PartsCatalog</TT> <TT>ShowAll()</TT> function calls <TT>PartsList</TT><TT>Iterate()</TT> with the appropriate pointer to member function of class <TT>Part</TT>.<TT>ShowAll()</TT> acts as a public interface to <TT>Iterate()</TT>, providing thecorrect information but preventing client classes from calling <TT>Iterate()</TT>dir-ectly. Although <TT>PartsList</TT> might allow other functions to be passed to<TT>Iterate()</TT>, <TT>PartsCatalog</TT> does not.</P><P>The <TT>Insert()</TT> function has changed as well. Note, on line 23, that <TT>Find()</TT>is now called directly, because it is inherited from the base class. The call online 24 to <TT>Insert()</TT> must be fully qualified, of course, or it would endlesslyrecurse into itself.</P><P>In short, when methods of <TT>PartsCatalog</TT> want to call <TT>PartsList</TT>methods, they may do so directly. The only exception is when <TT>PartsCatalog</TT>has overridden the method and the <TT>PartsList</TT> version is needed, in whichcase the function name must be qualified fully.</P><P>Private inheritance allows the <TT>PartsCatalog</TT> to inherit what it can use,but still provide mediated access to <TT>Insert</TT> and other methods to which clientclasses should not have direct access.<BLOCKQUOTE>	<P><HR><B>DO </B>inherit publicly when the derived object is a kind of the base class. <B>DO</B>	use containment when you want to delegate functionality to another class, but you	don't need access to its protected members.<B> DO</B> use private inheritance when	you need to implement one class in terms of another, and you need access to the base	class's protected members. <B>DON'T </B>use private inheritance when you need to	use more than one of the base class. You must use containment. For example, if <TT>PartsCatalog</TT>	needed two <TT>PartsLists</TT>, you could not have used private inheritance. <B>DON'T</B>	use public inheritance when members of the base class should not be available to	clients of the derived class. <HR></BLOCKQUOTE><H3 ALIGN="CENTER"><A NAME="Heading24"></A><FONT COLOR="#000077">Friend Classes</FONT></H3><P>Sometimes you will create classes together, as a set. For example, <TT>PartNode</TT>and <TT>PartsList</TT> were tightly coupled, and it would have been convenient if<TT>PartsList</TT> could have read <TT>PartNode</TT>'s <TT>Part</TT> pointer, <TT>itsPart</TT>,directly.</P><P>You wouldn't want to make <TT>itsPart</TT> public, or even protected, becausethis is an implementation detail of <TT>PartNode</TT> and you want to keep it private.You do want to expose it to <TT>PartsList</TT>, however.</P><P>If you want to expose your private member data or functions to another class,you must declare that class to be a friend. This extends the interface of your classto include the friend class.</P><P>Once <TT>PartsNode</TT> declares <TT>PartsList</TT> to be a friend, all of <TT>PartsNode</TT>'smember data and functions are public as far as <TT>PartsList</TT> is concerned.</P><P>It is important to note that friendship cannot be transferred. Just because youare my friend and Joe is your friend doesn't mean Joe is my friend. Friendship isnot inherited either. Again, just because you are my friend and I'm willing to sharemy secrets with you doesn't mean I'm willing to share my secrets with your children.</P><P>Finally, friendship is not commutative. Assigning <TT>Class One</TT> to be a friendof <TT>Class Two</TT> does not make <TT>Class Two</TT> a friend of <TT>Class One</TT>.Just because you are willing to tell me your secrets doesn't mean I am willing totell you mine.</P><P>Listing 15.7 illustrates friendship by rewriting the example from Listing 15.6,making <TT>PartsList</TT> a friend of <TT>PartNode</TT>. Note that this does notmake <TT>PartNode</TT> a friend of <TT>PartsList</TT>.</P><P><A NAME="Heading25"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 15.7. Friendclass illustrated.</B></FONT><PRE><FONT COLOR="#0066FF">0:      #include &lt;iostream.h&gt;1:    2:      typedef unsigned long ULONG;3:      typedef unsigned short USHORT;4:    5:    6:      // **************** Part ************7:    8:      // Abstract base class of parts9:      class Part10:       {11:       public:12:          Part():itsPartNumber(1) {}13:          Part(ULONG PartNumber):14:              itsPartNumber(PartNumber){}15:          virtual ~Part(){}16:          ULONG GetPartNumber() const 17:              { return itsPartNumber; }18:          virtual void Display() const =0; 19:       private:20:          ULONG itsPartNumber;21:       };22:     23:       // implementation of pure virtual function so that24:       // derived classes can chain up25:       void Part::Display() const26:       {27:           cout &lt;&lt; &quot;\nPart Number: &quot;;28:           cout &lt;&lt; itsPartNumber &lt;&lt; endl;29:       }30:     31:       // **************** Car Part ************32:     33:       class CarPart : public Part34:       {35:       public:36:          CarPart():itsModelYear(94){}37:          CarPart(USHORT year, ULONG partNumber);38:          virtual void Display() const 39:          { 40:              Part::Display(); 41:              cout &lt;&lt; &quot;Model Year: &quot;;42:              cout &lt;&lt; itsModelYear &lt;&lt; endl;  43:          }44:       private:45:          USHORT itsModelYear;46:       };47:     48:       CarPart::CarPart(USHORT year, ULONG partNumber):49:          itsModelYear(year),50:          Part(partNumber)51:       {}52:     53: 54:       // **************** AirPlane Part ************55:     56:       class AirPlanePart : public Part57:       {58:       public:59:          AirPlanePart():itsEngineNumber(1){};60:          AirPlanePart61:              (USHORT EngineNumber, ULONG PartNumber);62:          virtual void Display() const63:          { 64:              Part::Display(); 65:              cout &lt;&lt; &quot;Engine No.: &quot;;66:              cout &lt;&lt; itsEngineNumber &lt;&lt; endl;  67:          }68:       private:

⌨️ 快捷键说明

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