📄 index.html
字号:
<pre>class TeachingAssistant : public Student, public Employee
{
. . .
}</pre>
</font>
</td>
</tr>
<tr>
<td valign="top"><font size="+1" color="#009999">Purpose:</font></td>
<td><font size="+1">Define a class that inherits features from two or
more base classes.</font></td>
</tr>
</table>
</font>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">21.7 Muliple Inheritance (cont.)</font></h2>
<font size="+1">
<ul>
<li>Instances of derived classes maintain data fields of all base
classes:
<script><!--
image( "fig07.png" )
//--></script>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7 Muliple Inheritance (cont.)</font></h2>
<font size="+1">
<ul>
<li>The idea of polymorphic assignment applies for each of the base classes:
<blockquote><tt>
TeachingAssistant* fred = new TeachingAssistant();
<br>Employee* new_hire = fred;<font color="#0000cc">
// Legal, because a TeachingAssistant is-a Employee</font>
<br>Student* advisee = fred;<font color="#0000cc">
// Legal, because a TeachingAssistant is-a Student</font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7 Muliple Inheritance (cont.)</font></h2>
<font size="+1">
<ul>
<li>Dynamic cast and <tt>typeid</tt> work just as we'd like:
<blockquote>
<pre>Student* mary = . . .;
TeachingAssistant* lab_instructor
= dynamic_cast<TeachingAssistant*>(mary);
if (lab_instructor != NULL)
cout << "Yes, mary is a TeachingAssistant. \n";
else
cout << "No, mary is not a TeachingAssistant. \n";</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7.1 Name Ambiguity</font></h2>
<font size="+1">
<ul>
<li>Names of inherited operations may clash</li>
<li>E.g., suppose both <tt>Employee</tt> and <tt>Student</tt> provide a
<tt>get_id</tt> method, that refer to different IDs:
<blockquote><tt>
TeachingAssistant* fred = new TeachingAssistant();
<br><font color="#cc0000">cout << "Your number is " <<
fred->get_id() << "\n";</font>
<br><font color="#0000cc">// Error, ambiguous member function name</font>
</tt></blockquote>
</li>
<li>2 resolutions:</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7.1 Name Ambiguity (cont.)</font></h2>
<font size="+1">
<ol>
<li>Use the fully qualified function name:
<blockquote><tt>
cout << "Your teaching assistant is "<br>
<<
<nobr>fred->Employee::get_id()</nobr> << "\n";
</tt></blockquote>
</li>
</ol>
</font>
<hr><h2><font color="#009999">21.7.1 Name Ambiguity (cont.)</font></h2>
<font size="+1">
<ol start='2'>
<li>Redefine the ambiguous name in the new class:
<blockquote>
<pre>class TeachingAssistant : public Student, public Employee
{
public:
string get_id() const;
string student_id() const;
};</pre>
</blockquote>
</li>
</ol>
</font>
<hr><h2><font color="#009999">21.7.1 Name Ambiguity (cont.)</font></h2>
<font size="+1">
<ul>
<li>Hide the use of the qualified name within the body</li>
</ul>
<blockquote>
<pre>// get_id will return Employee identification number
string TeachingAssistant::get_id()
{
return Employee::get_id();
}
string TeachingAssistant::student_id()
// Make student value available by a different name
{
return Student::get_id();
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes</font></h2>
<font size="+1">
<ul>
<li>Base class is specified only once</li>
<li>A class may be inherited (indirectly) more than once</li>
<li>E.g., <tt>Person</tt> as a base class for <tt>Employee</tt> and
<tt>Student</tt>:
<blockquote>
<pre>class Person
{
public:
Person(string n);
string get_name() const;
private:
string name;
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes</font></h2>
<font size="+1">
<blockquote>
<pre>class Employee : public Person
{
. . .
};
class Student : public Person
{
. . .
};</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes (cont.)</font></h2>
<font size="+1">
<ul>
<li><tt>TeachingAssistant</tt> now has 2 <tt>name</tt> fields:
<script><!--
image( "un03.png" ) // page 781, 3
//--></script>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes (cont.)</font></h2>
<font size="+1">
<ul>
<li>If this is not desirable, specify inheritance as <tt>virtual</tt>:
<blockquote>
<pre>class Student : <font color="#009999">virtual</font> public Person
{
. . .
};
class Employee : <font color="#009999">virtual</font> public Person
{
. . .
};
class TeachingAssistant : public Student, public Employee
{
. . .
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes (cont.)</font></h2>
<font size="+1">
<ul>
<li>The intermediate classes need to use virtual inheritance</li>
<li>Virtual inheritance alters placement of base classes</li>
<script><!--
image( "fig08.png" ) // page 782, 3
//--></script>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes (cont.)</font></h2>
<font size="+1">
<ul>
<li>Duplicated data areas from the common base class are eliminated:
<script><!--
image( "fig09.png" ) // page 782, 3
//--></script>
</ul>
</font>
<hr><h2><font color="#009999">21.7.2 Replicated Base Classes (cont.)</font></h2>
<font size="+1">
<ul>
<li><tt>TeachingAssistant*</tt> can always be converted to an
<tt>Employee*</tt>, then to a <tt>Person*</tt></li>
<li>Without virtual inheritance, a <tt>TeachingAssistant*</tt> can <b>not</b>
be converted directly to a <tt>Person*</tt>:
<blockquote><tt>
TeachingAssistant* fred = new TeachingAssistant();
<br>Student* s = fred;<font color="#0000cc">
// Legal, because TeachingAssistant <nobr>is-a</nobr> Student</font>
<br>Person* p1 = s;
<br>Employee* e = fred;
<br>Person* p2 = e;
<br><font color="#009999">Person* p3 = fred;</font><font color="#0000cc">
// Legal if virtual inheritance used, otherwise error</font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.8 Software Frameworks</font></h2>
<font size="+1">
<ul>
<li>Modern programming emphasized software reuse</li>
<li>A reusable component must be general purpose</li>
<li>Details of an individual application are required</li>
<li>Polymorphism provides a handy solution:
<ul>
<li>A general base class is developed and distributed across many
projects</li>
<li>Use Inheritance to create specialized versions of the general base
class</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.8 Software Frameworks (cont.)</font></h2>
<font size="+1">
<ul>
<li>Consider the creation of GUI:</li>
<ul>
<li>Many different components</li>
<li>Each component may have complex behavior</li>
</ul>
</li>
<li>Rewriting this behavior for each new application would be difficult</li>
<li>Programmers employ a <i>software framework</i>, or <i>toolkit</i>:</li>
<ul>
<li>Collection of reusable classes and functions</li>
<li>A starting point used in the creation of new applications</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.8 Software Frameworks (cont.)</font></h2>
<font size="+1">
<p>Consider putting a window up on a screen. The concept of window is
generic.</p>
<ul>
<li>Put code to handle generic tasks, such as moving the window, in the base
class</li>
<li>For application-aware tasks, base class provides simple default behavior
or pure virtual functions:</li>
</ul>
</font>
<hr><h2><font color="#009999">21.8 Software Frameworks (cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>class wxWindow
{
public:
. . .
<font color="#0000cc">// Pure virtual member function</font>
virtual void OnPaint(wxPaintEvent& event) = 0;
virtual void OnMouseEvent(wxMouseEvent& event);
. . .
};
void wxWindow::OnMouseEvent(wxMouseEvent& event)
{
<font color="#0000cc">// Default behavior, do nothing</font>
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">21.8 Software Frameworks (cont.)</font></h2>
<font size="+1">
<ul>
<li>Each new application inherits from <tt>wxWindow</tt> to create a special
purpose class</li>
<li>Application-specific details can be filled in:</li>
</ul>
</font>
<hr><h2><font color="#009999">21.8 Software Frameworks (cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>class ClockWindow : public wxWindow
<font color="#0000cc">// ClockWindow will be developed in Chapter 27</font>
{
public:
. . .
virtual void OnPaint(wxPaintEvent& event);
virtual void OnMouseEvent(wxMouseEvent& event);
. . .
};
void ClockWindow::OnMouseEvent(wxMouseEvent& event)
{
. . . <font color="#0000cc">// Implement mouse events for this specific application</font>
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">Chapter Summary</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<ol>
<li>Inheritance can be used to organize classes into hierarchies.</li>
<li>Polymorphic variables are very powerful. Declared as one type, its
static type, but can maintain a value of a different type, its dynamic type.
Must be pointers or references.</li>
<li>When a virtual method is called using a polymorphic variable, its
dynamic type is used.
<li>A virtual method that is declared but not defined is called a pure
virtual method. A class with a pure virtual method can not be instantiated.
It is called an abstract class.</li>
</ol>
</font>
<hr><h2><font color="#009999">Chapter Summary (cont.)</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<ol start='5'>
<li>The dynamic type of a polymorphic variable can be tested using a dynamic
cast, or the <tt>typeid</tt> operator.</li>
<li>A class that inherits from two or more base classes is said to use
multiple inheritance.</li>
<li>A software framework (or toolkit) is a collection of classes and/or
functions that capture the common features of a task. Methods are overridden
to specialize behavior.</li>
</ol>
</font>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -