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

📄 ch13.htm

📁 vc的电子书
💻 HTM
📖 第 1 页 / 共 5 页
字号:
19:       
20:       virtual void Fly() { cout << "I can fly! I can fly! I can fly!\n"; }
21:    };
22:
23:    const int NumberHorses = 5;
24:    int main()
25:    {
26:       Horse* Ranch[NumberHorses];
27:       Horse* pHorse;
28:       int choice,i;
29:       for (i=0; i<NumberHorses; i++)
30:       {
31:          cout << "(1)Horse (2)Pegasus: ";
32:          cin >> choice;
33:          if (choice == 2)
34:             pHorse = new Pegasus;
35:          else
36:             pHorse = new Horse;
37:          Ranch[i] = pHorse;
38:       }
39:       cout << "\n";
40:       for (i=0; i<NumberHorses; i++)
41:       {
42:          Pegasus *pPeg = dynamic_cast< Pegasus *> (Ranch[i]);
42:          if (pPeg)
43:             pPeg->Fly();
44:          else
45:             cout << "Just a horse\n";
46:
47:          delete Ranch[i];
48:       }
49:  return 0;
<TT>50:</TT></FONT><TT>
</TT><FONT COLOR="#0066FF">
Output: (1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1

Just a horse
I can fly! I can fly! I can fly!
Just a horse
I can fly! I can fly! I can fly!
Just a horse
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>This solution also works.
<TT>Fly()</TT> is kept out of <TT>Horse</TT>, and is not called on <TT>Horse</TT>
objects. When it is called on <TT>Pegasus</TT> objects, however, they must be explicitly
cast; <TT>Horse</TT> objects don't have the method <TT>Fly()</TT>, so the pointer
must be told it is pointing to a <TT>Pegasus</TT> object before being used.</P>
<P>The need for you to cast the <TT>Pegasus</TT> object is a warning that something
may be wrong with your design. This program effectively undermines the virtual function
polymorphism, because it depends on casting the object to its real runtime type.
<H4 ALIGN="CENTER"><A NAME="Heading10"></A><FONT COLOR="#000077">Adding to Two Lists</FONT></H4>
<P>The other problem with these solutions is that you've declared <TT>Pegasus</TT>
to be a type of <TT>Horse</TT>, so you cannot add a <TT>Pegasus</TT> object to a
list of <TT>Birds</TT>. You've paid the price of either moving <TT>Fly()</TT> up
into <TT>Horse</TT>, or casting down the pointer, and yet you still don't have the
full functionality you need.</P>
<P>One final single inheritance solution presents itself. You can push <TT>Fly()</TT>,
<TT>Whinny()</TT>, and <TT>Gallop()</TT> all up into a common base class of both
<TT>Bird</TT> and <TT>Horse</TT>: <TT>Animal</TT>. Now, instead of having a list
of <TT>Bird</TT>s and a list of <TT>Horse</TT>s, you can have one unified list of
<TT>Animal</TT>s. This works, but percolates more functionality up into the base
classes.</P>
<P>Alternatively, you can leave the methods where they are, but cast down <TT>Horses</TT>
and <TT>Birds</TT> and <TT>Pegasus</TT> objects, but that is even worse!


<BLOCKQUOTE>
	<P>
<HR>
<B>DO</B> move functionality up the inheritance hierarchy. <B>DON'T</B> move interface
	up the inheritance hierarchy. <B>DO</B> avoid switching on the runtime type of the
	object--use virtual methods, templates, and multiple inheritance.<B> DON'T</B> cast
	pointers to base objects down to derived objects. 
<HR>


</BLOCKQUOTE>

<H3 ALIGN="CENTER"><A NAME="Heading11"></A><FONT COLOR="#000077">Multiple Inheritance</FONT></H3>
<P>It is possible to derive a new class from more than one base class. This is called
Multiple Inheritance. To derive from more than the base class, you separate each
base class by commas in the class designation. Listing 13.3 illustrates how to declare
<TT>Pegasus</TT> so that it derives from both <TT>Horses</TT> and <TT>Birds</TT>.
The program then adds <TT>Pegasus</TT> objects to both types of lists.</P>
<P><A NAME="Heading12"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 13.3. Multiple
inheritance.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1:     // Listing 13.3. Multiple inheritance.
2:     // Multiple Inheritance
3:
4:     #include &lt;iostream.h&gt;
5:
6:     class Horse
7:     {
8:     public:
9:        Horse() { cout &lt;&lt; &quot;Horse constructor... &quot;; }
10:       virtual ~Horse() { cout &lt;&lt; &quot;Horse destructor... &quot;; }
11:       virtual void Whinny() const { cout &lt;&lt; &quot;Whinny!... &quot;; }
12:    private:
13:       int itsAge;
14:    };
15:
16:    class Bird
17:    {
18:    public:
19:       Bird() { cout &lt;&lt; &quot;Bird constructor... &quot;; }
20:       virtual ~Bird() { cout &lt;&lt; &quot;Bird destructor... &quot;; }
21:       virtual void Chirp() const { cout &lt;&lt; &quot;Chirp... &quot;;  }
22:       virtual void Fly() const 
23:       { 
24:          cout &lt;&lt; &quot;I can fly! I can fly! I can fly! &quot;; 
25:       }
26:    private:
27:       int itsWeight;
28:    };
29:
30:    class Pegasus : public Horse, public Bird
31:    {
32:    public:
33:       void Chirp() const { Whinny(); }
34:       Pegasus() { cout &lt;&lt; &quot;Pegasus constructor... &quot;; }
35:       ~Pegasus() { cout &lt;&lt; &quot;Pegasus destructor...  &quot;; }
36:    };
37:
38:    const int MagicNumber = 2;
39:    int main()
40:    {
41:       Horse* Ranch[MagicNumber];
42:       Bird* Aviary[MagicNumber];
43:       Horse * pHorse;
44:       Bird * pBird; 
45:       int choice,i;
46:       for (i=0; i&lt;MagicNumber; i++)
47:       {
48:          cout &lt;&lt; &quot;\n(1)Horse (2)Pegasus: &quot;;
49:          cin &gt;&gt; choice;
50:          if (choice == 2)
51:             pHorse = new Pegasus;
52:          else
53:             pHorse = new Horse;
54:          Ranch[i] = pHorse;
55:       }
56:       for (i=0; i&lt;MagicNumber; i++)
57:       {
58:          cout &lt;&lt; &quot;\n(1)Bird (2)Pegasus: &quot;;
59:          cin &gt;&gt; choice;
60:          if (choice == 2)
61:             pBird = new Pegasus; 
62:          else
63:             pBird = new Bird;
64:          Aviary[i] = pBird;
65:       }
66:
67:       cout &lt;&lt; &quot;\n&quot;;
68:       for (i=0; i&lt;MagicNumber; i++)
69:       {
70:          cout &lt;&lt; &quot;\nRanch[&quot; &lt;&lt; i &lt;&lt; &quot;]: &quot; ;
71:          Ranch[i]-&gt;Whinny();
72:          delete Ranch[i];
73:       }
74:
75:       for (i=0; i&lt;MagicNumber; i++)
76:       {
77:          cout &lt;&lt; &quot;\nAviary[&quot; &lt;&lt; i &lt;&lt; &quot;]: &quot; ;
78:          Aviary[i]-&gt;Chirp();
79:          Aviary[i]-&gt;Fly();
80:          delete Aviary[i];
81:       }
82:     return 0;
<TT>83: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (1)Horse (2)Pegasus: 1
Horse constructor...
(1)Horse (2)Pegasus: 2
Horse constructor... Bird constructor... Pegasus constructor...
(1)Bird (2)Pegasus: 1
Bird constructor...
(1)Bird (2)Pegasus: 2
Horse constructor... Bird constructor... Pegasus constructor...

Ranch[0]: Whinny!... Horse destructor...
Ranch[1]: Whinny!... Pegasus destructor...  Bird destructor... Horse destructor...
Aviary[0]: Chirp... I can fly! I can fly! I can fly! Bird destructor...
Aviary[1]: Whinny!... I can fly! I can fly! I can fly! 
Pegasus destructor... Bird destructor... Horse destructor...
Aviary[0]: Chirp... I can fly! 
I can fly! I can fly! Bird destructor...
Aviary[1]: Whinny!... I can fly! I can fly! I can fly! 
Pegasus destructor.. Bird destructor... Horse destructor... 
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>On lines 6-14, a <TT>Horse</TT>
class is declared. The constructor and destructor print out a message, and the <TT>Whinny()</TT>
method prints the word <TT>Whinny!</TT></P>
<P>On lines 16-25, a <TT>Bird</TT> class is declared. In addition to its constructor
and destructor, this class has two methods: <TT>Chirp()</TT> and <TT>Fly()</TT>,
both of which print identifying messages. In a real program these might, for example,
activate the speaker or generate animated images.</P>
<P>Finally, on lines 30-36, the class <TT>Pegasus</TT> is declared. It derives both
from <TT>Horse</TT> and from <TT>Bird</TT>. The <TT>Pegasus</TT> class overrides
the <TT>Chirp()</TT> method to call the <TT>Whinny()</TT> method, which it inherits
from <TT>Horse</TT>.</P>
<P>Two lists are created, a <TT>Ranch</TT> with pointers to <TT>Horse</TT> on line
41, and an <TT>Aviary</TT> with pointers to <TT>Bird</TT> on line 42. On lines 46-55,
<TT>Horse</TT> and <TT>Pegasus</TT> objects are added to the <TT>Ranch</TT>. On lines
56-65, <TT>Bird</TT> and <TT>Pegasus</TT> objects are added to the <TT>Aviary</TT>.</P>
<P>Invocations of the virtual methods on both the <TT>Bird</TT> pointers and the
<TT>Horse</TT> pointers do the right things for <TT>Pegasus</TT> objects. For example,
on line 78 the members of the <TT>Aviary</TT> array are used to call <TT>Chirp()</TT>
on the objects to which they point. The <TT>Bird</TT> class declares this to be a
virtual method, so the right function is called for each object.</P>
<P>Note that each time a <TT>Pegasus</TT> object is created, the output reflects
that both the <TT>Bird</TT> part and the <TT>Horse</TT> part of the <TT>Pegasus</TT>
object is also created. When a <TT>Pegasus</TT> object is destroyed, the <TT>Bird</TT>
and <TT>Horse</TT> parts are destroyed as well, thanks to the destructors being made
virtual.
<H3 ALIGN="CENTER"><A NAME="Heading14"></A><FONT COLOR="#000077">Declaring Multiple
Inheritance</FONT></H3>
<P>Declare an object to inherit from more than one class by listing the base classes
following the colon after the class name. Separate the base classes by commas. Example
1:</P>
<PRE><FONT COLOR="#0066FF">
class Pegasus : public Horse, public Bird
</FONT></PRE>
<P>Example 2:</P>
<PRE><FONT COLOR="#0066FF">
class Schnoodle : public Schnauzer, public Poodle
</FONT></PRE>
<H4 ALIGN="CENTER"><A NAME="Heading15"></A><FONT COLOR="#000077">The Parts of a Multiply
Inherited Object</FONT></H4>
<P>When the <TT>Pegasus</TT> object is created in memory, both of the base classes
form part of the <TT>Pegasus</TT> object, as illustrated in Figure 13.1.<BR>
<BR>
<A NAME="Heading16"></A><A HREF="13zcp01.jpg" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/art/ch13/13zcp01.jpg"><FONT COLOR="#000077">Figure
13.1.</FONT></A><FONT COLOR="#000077"> </FONT><I>Multiply inherited objects.</I><BR>
<BR>
A number of issues arise with objects with multiple base classes. For example, what
happens if two base classes that happen to have the same name have virtual functions
or data? How are multiple base class constructors initialized? What happens if multiple
base classes both derive from the same class? The next sections will answer these
questions, and explore how multiple inheritance can be put to work.
<H4 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">Constructors in
Multiply Inherited Objects</FONT></H4>
<P>If <TT>Pegasus</TT> derives from both <TT>Horse</TT> and <TT>Bird</TT>, and each
of the base classes has constructors that take parameters, the <TT>Pegasus</TT> class
initializes these constructors in turn. Listing 13.4 illustrates how this is done.</P>
<P><A NAME="Heading18"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 13.4. Calling
multiple constructors.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1:     // Listing 13.4
2:     // Calling multiple constructors
3:     #include &lt;iostream.h&gt;
4:     typedef int HANDS;
5:     enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;
6:     enum BOOL { FALSE, TRUE };
7:
8:     class Horse
9:     {
10:    public:
11:       Horse(COLOR color, HANDS height);
12:       virtual ~Horse() { cout &lt;&lt; &quot;Horse destructor...\n&quot;; }
13:       virtual void Whinny()const { cout &lt;&lt; &quot;Whinny!... &quot;; }
14:       virtual HANDS GetHeight() const { return itsHeight; }
15:       virtual COLOR GetColor() const { return itsColor; }
16:    private:
17:       HANDS itsHeight;
18:       COLOR itsColor;
19:    };
20:
21:    Horse::Horse(COLOR color, HANDS height):
22:       itsColor(color),itsHeight(height)
23:    {
24:       cout &lt;&lt; &quot;Horse constructor...\n&quot;;
25:    }
26:
27:    class Bird
28:    {
29:    public:
30:       Bird(COLOR color, BOOL migrates);
31:       virtual ~Bird() {cout &lt;&lt; &quot;Bird destructor...\n&quot;;  }
32:       virtual void Chirp()const { cout &lt;&lt; &quot;Chirp... &quot;;  }
33:       virtual void Fly()const 
34:       { 
35:          cout &lt;&lt; &quot;I can fly! I can fly! I can fly! &quot;; 
36:       }
37:       virtual COLOR GetColor()const { return itsColor; }
38:       virtual BOOL GetMigration() const { return itsMigration; }
39: 
40:    private:
41:       COLOR itsColor;
42:       BOOL itsMigration;
43:    };
44:
45:    Bird::Bird(COLOR color, BOOL migrates):
46:       itsColor(color), itsMigration(migrates)
47:    {
48:       cout &lt;&lt; &quot;Bird constructor...\n&quot;;
49:    }
50:
51:    class Pegasus : public Horse, public Bird
52:    {

⌨️ 快捷键说明

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