📄 index.html
字号:
iframeWrapCode( "fraction.h", "90%", "75%" )
//--></script>
</font>
<hr><h2><font color="#009999">17.2 Case Study: Fractional Numbers
(<tt>fraction.cpp</tt>)</font></h2>
<font size="+1">
<p>(Discussion follows)
<script><!--
iframeWrapCode( "fraction.cpp", "90%", "75%" )
//--></script>
</font>
<hr><h2><font color="#009999">17.2 Case Study: Fractional Numbers
(<tt>fractiontest.cpp</tt>)</font></h2>
<font size="+1">
<script><!--
iframeWrapCode( "fractiontest.cpp", "90%", "75%" )
//--></script>
</font>
<hr><h2><font color="#009999">17.3 Overloading Simple Arithmetic
Operators</font></h2>
<font size="+1">
<ul>
<li><tt> = + - * / %</tt></li>
<li>Parameters types need <b>not</b> match
<blockquote><tt>
Time Time::operator+( int seconds ) const;
</tt></blockquote>
</li>
<li>Supply behavior that is analogous to the arithmetic operators;
intuitive</li>
<li><b>E.g.</b> (fraction.cpp, lines 61-67)
<br><i>(See next slide)</i>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.3 Simple Arithmetic Operators - Fraction
Example</font></h2>
<font size="+1">
<i>a/b + c/d</i> is defined to be <i>(a*d + c*d)/(b*d)</i><br><br>
<blockquote>
<pre>Fraction operator+(const Fraction& left, const Fraction& right)
{
Fraction result(left.numerator() * right.denominator()
+ right.numerator() * left.denominator(),
left.denominator() * right.denominator());
return result;
}</pre>
</blockquote>
<p>The remaining operations are defined similarly
</font>
<hr><h2><font color="#009999">17.3 Unary Arithmetic Operators</font></h2>
<font size="+1">
<ul>
<li> <tt>+ - * &</tt> have both binary and unary forms</li>
<li>To overload unary form, reduce the number of parameters by one</li>
<li><b>E.g.:</b>
<blockquote>
<pre>Fraction operator-(const Fraction& value)
{
Fraction result(-value.numerator(), value.denominator());
return result;
}</pre>
</blockquote>
</li>
<li>A unary operator defined as a member function takes no arguments
(sect. 17.6)</li>
</ul>
</font>
<hr><h2><font color="#009999">17.4 Overloading Comparison Operators</font></h2>
<font size="+1">
<ul>
<li>Similar to the arithmetic operators
<li><i>Not</i> supplied automatically</li>
<li>Typically return a <tt>bool</tt>
<li><b>E.g.:</b> <tt>Time</tt>s are equal <=> difference is 0
<blockquote>
<pre>bool operator==(const Time& a, const Time& b)
{
return a.seconds_from(b) == 0;
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.4 Overloading Comparison Operators</font></h2>
<font size="+1">
<ul>
<li><b>E.g.</b>, from the <tt>Fraction</tt> class:
<blockquote>
<pre>bool operator==(const Fraction&amp; left, const Fraction&amp; right)
{
return left.numerator() * right.denominator()
== right.numerator() * left.denominator();
}
bool operator<(const Fraction& left, const Fraction& right)
{
return left.numerator() * right.denominator()
< right.numerator() * left.denominator();
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">Productivity Hint 17.2</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Define Comparisons in Terms of Each Other</font></h3>
<ul>
<li>Write 1 or 2 member functions; equality, and strict inequality</li>
<li>Define all comparisons in terms of these functions</li>
<li><b>E.g.:</b> <tt>Fraction</tt> class (fraction.cpp)
<ul>
<li>A single <tt>compare</tt> method (line 97), returns an
<tt>int</tt></li>
<li>All 6 comparison operators (lines 104-132) call <tt>compare</tt></li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">Advanced Topic 17.2</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Symmetry and Conversion</font></h3>
<ul>
<li>Arithmetic and comparison operators are generally nonmember
functions</li>
<li>No implicit conversions of left operand for member functions:
<ul>
<p>Consider <tt>Fraction a;</tt></p>
<li><tt>( a == 2 )</tt> works fine (given the constructors)</li>
<li><tt>( 2 == a )</tt> will <b>not</b> work if equality is a member
function.
</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.5 Overloading Input <tt>>></tt> and
Output <tt><<</tt></font></h2>
<font size="+1">
<ul>
<li>Originally shift operators</li>
<li>Almost always overloaded for I/O</li>
<li>Overloaded exactly as the binary arithmetic operators</li>
<li>Should be non-member functions</li>
</ul>
</font>
<hr><h2><font color="#009999">17.5.1 Stream Output <<</font></h2>
<font size="+1">
<ul>
<li>Output stream class (chptr. 12) provides ability to write a single
character</li>
<li>Stream library provides insertion operator for all built-in types:
<blockquote><tt>
ostream& operator<<(ostream& out, double value);
</tt></blockquote>
<p><b>Note:</b> the stream itself is returned</p>
</li>
<li><b>E.g.:</b> Overload output for <tt>Fraction</tt>
<blockquote><tt>
<pre>ostream& operator<<( ostream &out, const Fraction &value )
{
out << value.numerator() << "/" << value.denominator();
return out;
}</pre>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.5.2 Stream Input >></font></h2>
<font size="+1">
<ul>
<li>Stream library provides for all built-in types</li>
<li>Can be overloaded, much like the output operator</li>
<li>2nd parameter is a <i>non-const</i> reference
<li><b>E.g.:</b> Input operator for <tt>Time</tt></li>
</ul>
</font>
<hr><h2><font color="#009999">17.5.2 Stream Input >> (cont.)</font></h2>
<font size="+1">
<blockquote>
Assume a <tt>Time</tt> is input as 3 separate integers,
<tt>9 15 00</tt> to represent 9:15:00 a.m.
<br><br><tt>
<pre>istream& operator>>(istream& in, Time& a)
{
int hours;
int minutes;
int seconds;
in >> hours >> minutes >> seconds;
a = Time(hours, minutes, seconds);
return in;
}</pre></tt>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">Advanced Topic 17.3</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<h3><font color="#009999">Peeking at the Input</font></h3>
<p>You may put a single character back into the stream.
<p><b>E.g.:</b> We want to allow a user to input a <tt>Fraction</tt> as
a single integer (<tt>7</tt>), or as an integer, slash, integer (<tt>3/4</tt>)
</font>
<hr><h2><font color="#009999">Advanced Topic 17.3 (cont.)</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<blockquote>
<pre>istream& operator>>(istream& in, Fraction& r)
{
int t, b;
<font color="#0000cc">// Read the top</font>
in >> t;
<font color="#0000cc">// If there is a slash, read the next number</font>
char c;
in >> c;
if (c == '/')
in >> b;
else
{
in.putback(c);
b = 1;
}
r = Fraction(t, b);
return in;
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">17.6 Overloading Increment
and Decrement Operators</font></h2>
<font size="+1">
<ul>
<li>Generally defined as member functions</li>
<li>Two versions of each:
<ol>
<li>prefix version: <tt>++x</tt></li>
<li>postfix version: <tt>x++</tt></li>
</ol>
</li>
<li>C++ uses an extra argument to distinguish the postfix form</li>
</ul>
</font>
<hr><h2><font color="#009999">17.6 Overloading Increment
and Decrement Operators</font></h2>
<font size="+1">
<ul>
<li><b>E.g.:</b> Increments for <tt>Fraction</tt>
<br>Notice:
<ul>
<li>Prefix returns a reference</li>
<li>Postfix does more work</li>
</li>
</ul>
<blockquote>
<pre>class Fraction
{
. . .
Fraction& operator++(); <font color="#0000cc">// Prefix form</font>
Fraction operator++(int unused); <font color="#0000cc">// Postfix form</font>
. . .
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.6 Overloading Increment
and Decrement Operators (cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>Fraction& Fraction::operator++()
{
top += bottom;
return *this;
}
Fraction Fraction::operator++(int unused)
{
Fraction clone(top, bottom);
top += bottom;
return clone;
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">17.6.1 Iterators and Overloaded Operators</font></h2>
<font size="+1">
<ul>
<li>Iterators (Sect. 16.5) can be used just like pointers (Chptr. 10) to
process arrays</li>
<li>Iterators can be used (in varying capacities) on all standard
containers</li>
<li>Operators overloaded for iterators:
<table>
<tr><td width='25%'><tt>+</tt></td><td>addition</td></tr>
<tr><td><tt>==</tt></td><td>comparison</td></tr>
<tr><td><tt>*</tt></td><td>dereference</td></tr>
<tr><td><tt>++</tt></td><td>increment (post and pre)</td></tr>
</table>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.6.1 Example: Implementing Iterator Operators
</font></h2>
<font size="+1">
<p>Recall <tt>Iterator</tt>, defined on our <tt>List</tt> of strings. We can
now overload the standard operators:</p>
<blockquote>
<pre>Iterator& Iterator::operator++(int)
{
position = position->next;
return *this;
}
string Iterator::operator*() const
{
assert(position != NULL);
return position->data;
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">17.6.1 Example: Implementing Iterator Operators
(cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>bool Iterator::operator==(const Iterator& b) const
{
return position == b.position;
}
bool Iterator::operator!=(const Iterator& b) const
{
return position != b.position;
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">17.7 Overloading the Assignment
Operators</font></h2>
<font size="+1">
<h3><font color="#009999">The Assignment Operator,
<tt>=</tt></font></h3>
<ul>
<li>Must be a member function</li>
<li>Is <i>automatically generated</i>
<ul>
<li>Member-wise copy</li>
<li>Destructor and copy constructor also supplied by compiler</li>
</ul>
</li>
<li>Desired behavior for many classes</li>
<li>Explicitly supply if class has outside references</li>
</ul>
</font>
<hr><h2><font color="#009999">17.7.1 Overloading Compound Assignment
Operators (<tt>+= *=</tt>, etc.)</font></h2>
<font size="+1">
<ul>
<li><i>Never</i> supplied automatically</li>
<li>Use existing arithmetic and assignment operators to define compound
operator</li>
<li><b>E.g.:</b> <tt>+=</tt> for <tt>Fraction</tt></li>
<blockquote>
<pre>Fraction& Fraction::operator+=(const Fraction& right)
{
top = top * right.denominator() + bottom * right.numerator();
bottom *= right.denominator();
normalize();
return *this;
}</pre>
</blockquote>
</ul>
</font>
<hr><h2><font color="#009999">17.8 Overloading Conversion Operators</font></h2>
<font size="+1">
<ul>
<li>Conversion <i>to</i> a user-defined type is handled by constructors
<p><b>E.g.:</b> <tt>Fraction</tt> has a constructor that takes a
single integer. This is okay:
<blockquote><tt>
Fraction a(3,4), b;<br>
b = a + 2; <font color="#0000cc">// Addition of Fraction and integer</font>
</tt></blockquote>
<p>The assignment statement becomes</p>
<blockquote><tt>
b = a + Fraction(2);<br>
<font color="#0000cc">// Convert right operand to Fraction, then add</font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">17.8 Overloading Conversion Operators</font></h2>
<font size="+1">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -