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

📄 chap01.htm

📁 This is the second part of that lab manual to teach you how to make real-time programme and how to d
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:C:\TEMP\TicV2\html\TicV2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:09/26/2001
Translation Time:08:32:19
Translation Platform:Win32
Number of Output files:19
This File:C:\TEMP\TicV2\html\Chap01.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>1: Exception handling</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
    [ <a href="README.txt">Viewing Hints</a> ]
    [ <a href="RevisionHistory.htm">Revision History</a> ]
    [ <a href="http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html">Book Home Page</a> ]
    [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/Services">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  Thinking in C++, 2nd edition, Volume 2<br>
  <small>Revision 4.0</small></FONT></H2>
  <H3><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  by Bruce Eckel &amp; Chuck Allison<br>&copy;2001 MindView, Inc.</FONT></H3>
  
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
     [ <a href="Part1.htm">Previous Chapter</a> ] 
    
    [ <a href="SimpCont.htm">Short TOC</a> ] 
    [ <a href="Contents.htm">Table of Contents</a> ] 
  
        [ <a href="DocIdx.htm">Index</a> ]
        
     [ <a href="Chap02.htm">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc305593295"></A><A NAME="_Toc305628767"></A><A NAME="_Toc312374110"></A><A NAME="_Toc519041879"></A><A NAME="Heading18"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
1: Exception handling</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>Improved error
recovery<A NAME="Index13"></A> is one of the most powerful ways you can increase
the robustness of your code.</FONT><BR>show how you can make several function
calls with only one catch, thus greatly reducing the amount of error-handling
code you must write.<BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Unfortunately, it&#8217;s almost accepted
practice to ignore error conditions, as if we&#8217;re in a state of denial
about errors. Some of the reason is no doubt the tediousness and code bloat of
checking for many errors. For example,
<B>printf(&#160;)<A NAME="Index14"></A></B> returns the number of characters
that were successfully printed, but virtually no one checks this value. The
proliferation of code alone would be disgusting, not to mention the difficulty
it would add in reading the code.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The problem with C&#8217;s approach to
error handling could be thought of as one of coupling &#8211; the user of a
function must tie the error-handling code so closely to that function that it
becomes too ungainly and awkward to use.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the major features in C++ is
<I>exception handling</I>, which is a better way of thinking about and handling
errors. With exception handling<A NAME="Index15"></A>,</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Error-handling code is not
nearly so tedious to write, and it doesn't become mixed up with your "normal"
code. You write the code you <I>want</I> to happen; later in a separate section
you write the code to cope with the problems. If you make multiple calls to a
function, you handle the errors from that function once, in one
place.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Errors cannot
be ignored. If a function needs to send an error message to the caller of that
function, it &#8220;throws&#8221; an object representing that error out of the
function. If the caller doesn&#8217;t &#8220;catch&#8221; the error and handle
it, it goes to the next enclosing scope, and so on until <I>someone</I> catches
the error. </FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This chapter
examines C&#8217;s approach to error handling (such as it is), why it did not
work very well for C, and why it won&#8217;t work at all for C++. Then
you&#8217;ll learn about <B>try</B>, <B>throw</B>,<B> </B>and <B>catch</B>, the
C++ keywords that support exception
handling.</FONT><A NAME="_Toc305593296"></A><A NAME="_Toc305628768"></A><A NAME="_Toc312374111"></A><A NAME="_Toc519041880"></A><BR></P></DIV>
<A NAME="Heading19"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Error handling in C<BR><A NAME="Index16"></A><A NAME="Index17"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In most of the examples in this book,
<B>assert(&#160;)</B> was used as it was intended: for debugging during
development with code that could be disabled with <B>#define</B> <B>NDEBUG</B>
for the shipping product. Runtime error checking uses the <B>require.h</B>
functions developed in Chapter XX. These were a convenient way to say,
&#8220;There&#8217;s a problem here you&#8217;ll probably want to handle with
some more sophisticated code, but you don&#8217;t need to be distracted by it in
this example.&#8221; The <B>require.h</B> functions may be enough for small
programs, but for complicated products you may need to write more sophisticated
error-handling code.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Error handling is quite straightforward
in situations where you check some condition and you know exactly what to do
because you have all the necessary information in that context. Of course, you
just handle the error at that point. These are ordinary errors and not the
subject of this chapter. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The problem occurs when you
<I>don&#8217;t</I> have enough information in that context, and you need to pass
the error information into a larger context where that information does exist.
There are three typical approaches in C to handle this
situation.</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Return error information
from the function or, if the return value cannot be used this way, set a global
error condition flag. (Standard C provides
errno</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">
<A NAME="Index18"></A>and perror(&#160;)<A NAME="Index19"></A> to support this.)
As mentioned before, the programmer may simply ignore the error information
because tedious and obfuscating error checking must occur with each function
call. In addition, returning from a function that hits an exceptional condition
may not make sense.</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Use the little-known
Standard C library signal-handling system, implemented with the
signal(&#160;</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">)<A NAME="Index20"></A>
function (to determine what happens when the event occurs) and
raise(&#160;)<A NAME="Index21"></A> (to generate an event). Again, this has high
coupling because it requires the user of any library that generates signals to
understand and install the appropriate signal-handling mechanism; also in large
projects the signal numbers from different libraries may clash with each
other.</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Use the nonlocal
got</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">o<A NAME="Index22"></A><A NAME="Index23"></A>
functions in the Standard C library: setjmp(&#160;)<A NAME="Index24"></A> and
longjmp(&#160;)<A NAME="Index25"></A>. With setjmp(&#160;) you save a known good
state in the program, and if you get into trouble, longjmp(&#160;) will restore
that state. Again, there is high coupling between the place where the state is
stored and the place where the error occurs.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When considering error-handling schemes
with C++, there&#8217;s an additional very critical problem: The C techniques of
signals and setjmp/longjmp do not call destructors, so objects aren&#8217;t
properly cleaned up. This makes it virtually impossible to effectively recover
from an exceptional condition because you&#8217;ll always leave objects behind
that haven&#8217;t been cleaned up and that can no longer be accessed. The
following example demonstrates this with setjmp/longjmp:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C01:Nonlocal.cpp</font>
<font color=#009900>// setjmp() &amp; longjmp()</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;iostream&gt;
#include &lt;csetjmp&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Rainbow {
<font color=#0000ff>public</font>:
  Rainbow() { cout &lt;&lt; <font color=#004488>"Rainbow()"</font> &lt;&lt; endl; }
  ~Rainbow() { cout &lt;&lt; <font color=#004488>"~Rainbow()"</font> &lt;&lt; endl; }
};

jmp_buf kansas;

<font color=#0000ff>void</font> oz() {
  Rainbow rb;
  <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 3; i++)
    cout &lt;&lt; <font color=#004488>"there's no place like home\n"</font>;
  longjmp(kansas, 47);
}

<font color=#0000ff>int</font> main() {
  <font color=#0000ff>if</font>(setjmp(kansas) == 0) {
    cout &lt;&lt; <font color=#004488>"tornado, witch, munchkins...\n"</font>;
    oz();
  } <font color=#0000ff>else</font> {
    cout &lt;&lt; <font color=#004488>"Auntie Em! "</font>
         &lt;&lt; <font color=#004488>"I had the strangest dream..."</font>
         &lt;&lt; endl;
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>setjmp(&#160;)</B> is an odd function
because if you call it directly, it stores all the relevant information about
the current processor state in the <B>jmp_buf</B> and returns zero. In that case
it has the behavior of an ordinary function. However, if you call
<B>longjmp(&#160;)</B> using the same <B>jmp_buf</B>, it&#8217;s as if
you&#8217;re returning from <B>setjmp(&#160;)</B> again &#8211; you pop right
out the back end of the <B>setjmp(&#160;)</B>. This time, the value returned is
the second argument to <B>longjmp(&#160;)</B>, so you can detect that
you&#8217;re actually coming back from a <B>longjmp(&#160;)</B>. You can imagine
that with many different <B>jmp_buf</B>s, you could pop around to many different
places in the program. The difference between a local <B>goto</B> (with a label)
and this nonlocal goto is that you can go <I>anywhere</I> with setjmp/longjmp
(with some restrictions not discussed here).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The problem with C++ is that
<B>longjmp(&#160;)</B> doesn&#8217;t respect objects; in particular it
doesn&#8217;t call destructors when it jumps out of a
scope.</FONT><A NAME="fnB4" HREF="#fn4">[4]</A><FONT FACE="Georgia"> Destructor
calls are essential, so this approach won&#8217;t work with
C++.</FONT><A NAME="_Toc305593297"></A><A NAME="_Toc305628769"></A><A NAME="_Toc312374112"></A><A NAME="_Toc519041881"></A><BR></P></DIV>
<A NAME="Heading20"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Throwing an exception<BR><A NAME="Index26"></A><A NAME="Index27"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you encounter an exceptional situation
in your code &#8211; that is, one where you don&#8217;t have enough information
in the current context to decide what to do &#8211; you can send information
about the error into a larger context by creating an object containing that
information and &#8220;throwing&#8221; it out of your current context. This is
called <I>throwing an exception</I>. Here&#8217;s what it looks
like:</FONT><BR></P></DIV>

⌨️ 快捷键说明

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