📄 index.html
字号:
<!-- -*-html-*-
$Source: /usr/local/cvsroot/BigC++/21/index.html,v $
$Revision: 1.6 $
Big C++, chptr 21
editor: cols=80, tabstop=2
(c) 2005 John Wiley & Sons
Kurt Schmidt, kschmidt@cs.drexel.edu
NOTES
- 3 spaces are used for each indent in examples
REVISIONS:
- $Log: index.html,v $
- Revision 1.6 2004/04/20 22:02:58 kurt
- Made slides smaller (view %150, on 1024x768 display)
-
- Revision 1.5 2004/02/23 04:44:45 kurt
- linked in images, cribbed verbage
-
- Revision 1.4 2004/02/03 02:45:56 kurt
- Pared language, split slides
-
- Revision 1.3 2004/01/21 13:34:14 kurt
- fixed spelling
-
- Revision 1.2 2004/01/20 06:03:19 kurt
- first pass
-
- Revision 1.1 2004/01/20 03:16:48 kurt
- Creation
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Copyright" content="2005 John Wiley & Sons">
<meta name="Author" content="Kurt Schmidt">
<script language="JavaScript" src="./config.js"></script>
<script language="JavaScript" src="./pageFormat.js"></script>
<script><!-- // Set title on page
title()
//--></script>
</head>
<body>
<hr><h2><font color="#009999" size="+3">Chapter 21 - Polymorphism</font></h2>
<font size="+1">
<script><!-- // Set title on page
image( "cover.png" )
//--></script>
</font>
<hr><h2><font color="#009999" size="+2">Chapter Goals</font></h2>
</font>
<hr noshade size="4" color="#009999">
<font size="+1">
<ul>
<li>To be able to describe the information conveyed by a class hierarchy</li>
<li>To understand the concept of the polymorphic variable and its relationship
to class hierarchies</li>
<li>To understand the interaction between polymorphism and memory
management</li>
<li>To understand how to distinguish between virtual and nonvirtual overriding
and the uses of each</li>
<li>To understand the concept of downcasting, moving both up and down the
class hierarchy</li>
<li>To understand the concept of multiple inheritance</li>
<li>To learn how to design and use software frameworks</li>
</ul>
</font>
<hr><h2><font color="#009999">21.1 Class Inheritance Hierarchies</font></h2>
<font size="+1">
<ul>
<li>Hierarchies often used to categorize concepts</li>
<li>Often represented using trees:
<script><!--
image( "fig01.png" )
//--></script>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.1 Class Inheritance Hierarchies (cont.)
</font></h2>
<font size="+1">
<ul>
<li>The class inheritance relationship (is-a) fits this pattern</li>
<li>Base classes at the top, derived classes below</li>
<li>Each level linked to the object above by a <i>is-a</i> relationship</li>
<li>Each derived class is more specialized</li>
</ul>
</font>
<hr><h2><font color="#009999">21.1 Class Inheritance Hierarchies
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Some hierarchies are short:</li>
</ul>
<script><!--
image( "fig02.png" )
//--></script>
<ul>
<li>Forest vs. Tree</li>
</ul>
</font>
<hr><h2><font color="#009999">21.1 Class Inheritance Hierarchies
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Others can be complex:</li>
</ul>
<script><!--
image( "fig03.png" )
//--></script>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables</font></h2>
<font size="+1">
<ul>
<li>Powerful mechanism in the OO paradigm</li>
<li>Polymorphic - many forms</li>
<li>Consider our <tt>Employee</tt> class:
<ul>
<li>add <tt>annual_income</tt> method</li>
<li>for <tt>Employee</tt>, this is equal to their yearly salary</li>
<li>inherit <tt>Manager</tt> from <tt>Employee</tt></li>
<li>a <tt>Manager's</tt> annual income is the sum of their salary
and bonus</li>
</ul>
(Code on next slide)
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables - example</font></h2>
<font size="+1">
<blockquote>
<pre>class Employee
{
public:
Employee(string n, double s);
string get_name() const;
double get_salary() const;
void set_salary(double s);
virtual double annual_income() const;
void print(ostream& out) const;
private:
string name;
double salary;
};</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables - example (cont.)
</font></h2>
<font size="+1">
<blockquote>
<pre>double Employee::annual_income() const
{
return get_salary();
}</pre>
<pre>class Manager : public Employee
{
public:
Manager(string n, double s, double b);
virtual double annual_income() const;
private:
double bonus;
};</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables - example (cont.)
</font></h2>
<font size="+1">
<blockquote>
<pre>Manager::Manager(string n, double s, double b)
: Employee(n, s), bonus(b) {}
double Manager::annual_income() const
{
return get_salary() + bonus;
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables (cont.)</font></h2>
<font size="+1">
<ul>
<li>Pointer or reference declared with one type</li>
<li>May hold a variable of a derived type:
<blockquote><tt>
Employee* emp = new Manager("Sarah Smith", 67000, 2000);
</tt></blockquote>
<ul>
<li><tt>Employee*</tt> is the <i>static type</i></li>
<li><tt>Manager*</tt> is the <i>dynamic type</i></li>
</ul>
</li>
<li>Dynamic type determined at run time</li>
<ul>
<li>Can change during execution</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables - Dynamic
Binding</font></h2>
<font size="+1">
<ul>
<li>Power lies with dynamic binding</li>
<li>A method invoked via polymorphic variable might execute the method
of the dynamic type</li>
<li>If the type changes during execution, so might the method selected</li>
</ul>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables - Dynamic
Binding</font></h2>
<font size="+1">
<ul>
<li>E.g., store members of a department in a vector of <tt>Employee</tt>
pointers:
<blockquote><tt>
vector<Employee*> department(3);<br>
department[0] = new Manager("Sarah Smith", 67000, 2000);<br>
department[1] = new Employee("Lisa Lim", 36000);<br>
department[2] = new Employee("Harry Hacker", 42000);
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.2 Polymorphic Variables - Dynamic
Binding (cont.)</font></h2>
<font size="+1">
<ul>
<li>Print out information regarding each employee:
<blockquote>
<pre>for (int i = 0; i < department.size(); i++)
{
cout << "Employee: "
<< department[i]->get_name() << " income "
<< department[i]->annual_income() << "\n";
}</pre>
</blockquote>
</li>
<li>Different <tt>annual_income</tt>s are being called:
<blockquote><tt>
Employee Sarah Smith income 69000<br>
Employee Lisa Lim income 36000<br>
Employee Harry Hacker income 42000
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.3 Virtual and Nonvirtual Overriding</font></h2>
<font size="+1">
<ul>
<li>Override method in derived class</li>
<li>Which method to execute:
<ul>
<li><i>statically bound</i> - invoked through a static type</li>
<li><i>dynamically bound</i> - invoked through a dynamic type</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.3 Virtual and Nonvirtual Overriding
(cont.)</font></h2>
<font size="+1">
<ul>
<li>If an <i>object</i> invokes an operation, statically bound:
<blockquote><tt>
Employee e("Lisa Lim", 36000);<br>
cout << e.annual_income() << "\n"; <font color="#0000cc">// Statically bound</font>
</tt></blockquote>
</li>
<li>If a <i>virtual</i> method is invoked through a <i>pointer</i> or a
<i>reference</i>, it is bound dynamically:
<blockquote><tt>
Employee* e = new Manager("Sarah Smith", 67000, 2000);<br>
cout << <font color="#009999">e->get_salary()</font>
<< "\n";<br>
<font color="#0000cc">
// Static binding, because get_salary is not virtual</font><br>
cout << <font color="#009999">e->annual_income()</font>
<< "\n";<br>
<font color="#0000cc">
// Dynamic binding, because annual_income is virtual</font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.3 Virtual and Nonvirtual Overriding
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Methods invoked via <tt>this</tt> ptr follow same rules:
<blockquote>
<pre>void Employee::print(ostream& out) const
{
out << "Name " << get_name()
<font color="#0000cc">// Static binding, same as Employee::get_name()</font>
<< " income " << annual_income() << "\n";
<font color="#0000cc">// Dynamic binding, same as this->annual_income()</font>
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">21.3 Virtual and Nonvirtual Overriding
(cont.)</font></h2>
<font size="+1">
<ul>
<li>The use of the dynamic type applies only to the <i>selector</i> of
a member function</li>
<li>Dynamic types of arguments are <i>not</i> considered in determination
of a function for execution:</li>
</ul>
</font>
<hr><h2><font color="#009999">21.3 Virtual and Nonvirtual Overriding
(cont.)</font></h2>
<font size="+1">
<ul>
<blockquote>
<pre>ostream& operator<<(ostream& out, const Employee& e)
{
out << "Employee " << e.name();
return out;
}
ostream& operator<<(ostream& out, const Manager& m)
{
out << "Manager " << e.name();
return out;
}
Manager man = new Manager(. . .);
cout << *man << "\n"; <font color="#0000cc">// Executes Manager function</font></pre>
</blockquote>
</ul>
</font>
<hr><h2><font color="#009999">21.3 Virtual and Nonvirtual Overriding
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Passing an instance of a derived class might be confusing:
<blockquote>
<pre>void print(ostream& out, Employee& emp)
{
out << emp << "\n";
}
print(cout, *man);
<font color="#0000cc">// Will print name as Employee not as Manager</font></pre>
</blockquote>
</li>
<li><tt>emp</tt>'s static type (<tt>Employee</tt>) is used to choose
<tt>operator<<</tt></li>
<li>Try restructuring the flow of control (next slide):</li>
</ul>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -