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

📄 reeves.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">
<HTML>
<HEAD>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>
<TITLE>Coping with Exceptions. By Jack Reeves</TITLE>

<SCRIPT LANGUAGE="JavaScript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript">var imagemax = 0; setCurrentMax(0);</SCRIPT>
<SCRIPT LANGUAGE="JavaScript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" SRC="../JAVA/SENDMETO.JS"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
var dingbase = "RE_DIR.HTM";
var dingtext = "Reeves, P";
if (self == top) {
 top.location.replace(dingbase + this.location.hash);
}
</SCRIPT>
</HEAD>

<BODY BGCOLOR="#FFFFFF" ONLOAD="setResize()">
<!-- SectionName="Reeves' Coping with Exceptions" -->
<HR SIZE="1" NOSHADE>
<FONT COLOR="#663300" FACE="Helvetica" SIZE=-1>
<B>This is an updated version of an article that appeared in the
    March 1996 issue of the <NOBR><FONT COLOR="#FF0000" SIZE="-2">&deg;</FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=cppreport"
    ONMOUSEOVER="self.status='C++ Report Home Page'; return true" ONMOUSEOUT="self.status=self.defaultStatus" TARGET="_top"><I>C++</NOBR> Report</I></A>.</FONT></B>

<HR SIZE="1" NOSHADE>

<P><A NAME="dingp1"></A><FONT ID="agtitle">Coping with Exceptions</FONT><SCRIPT>create_link(1);</SCRIPT>
</P>

<A NAME="AUTO00001"></A>

<P><A NAME="dingp2"></A><FONT FACE="Arial" SIZE="+1">by <FONT COLOR="#FF0000" SIZE="+1"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=reeves" ONMOUSEOVER = "self.status = 'Jack Reeves Home Page'; return true" ONMOUSEOUT = "self.status = self.defaultStatus" TARGET="_top">Jack W. Reeves</A></FONT><SCRIPT>create_link(2);</SCRIPT>
</P><!-- link to home page -->

<P><A NAME="dingp3"></A>In April 1995 the <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=ansi" ONMOUSEOVER="self.status='ANSI Home Page'; return true" ONMOUSEOUT="self.status=self.defaultStatus" TARGET="_top">ANSI</NOBR></A><NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=iso" ONMOUSEOVER="self.status='ISO Home Page'; return true" ONMOUSEOUT="self.status=self.defaultStatus" TARGET="_top">ISO</NOBR></A> C++ committee released the Committee Draft of the C++ Standard.  This draft freezes the feature set of the language and the standard libraries.  In the Standard, Chapter 15 - Exception Handling takes only 7 pages.  Of all the language chapters (1-16), only Chapter 1 (General: 6 pages), Chapter 4 (Standard Conversions: 4 pages) and Chapter 6 (Statements: 7 pages) are less than or equal in length. One might conclude from this that exceptions are an easy concept to specify and that there are not a lot of subtle details that need to be understood.  Looks can be <NOBR>deceiving.<SCRIPT>create_link(3);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp4"></A><A NAME="AUTO00002"></A>When I started to use exceptions, it rapidly became apparent that exceptions are much more difficult to use effectively than it first appears.  In fact, the more I explored how exceptions can interact with non-exception handling code, the more convinced I became that exceptions may be the most difficult feature of C++ to use.  I identified 3 reasons for this <NOBR>difficulty:<SCRIPT>create_link(4);</SCRIPT>
</NOBR></P>

<UL TYPE="i">
	<A NAME="dingp5"></A><LI> In order to be effective, exception handling must pervade the entire application &#151; it can not be localized to a function or even a class.<SCRIPT>create_link(5);</SCRIPT>

<A NAME="AUTO00003"></A>
	<A NAME="dingp6"></A><LI> Exceptions are almost like asynchronous events &#151; they do not respect semi-colons and can appear from the middle of an expression.<SCRIPT>create_link(6);</SCRIPT>

<A NAME="AUTO00004"></A>
	<A NAME="dingp7"></A><LI> Exceptions can not be ignored or &quot;put off&quot; &#151; if not handled an exception will propagate up the call stack, eventually aborting the entire program.<SCRIPT>create_link(7);</SCRIPT>


</UL>

<P><A NAME="dingp8"></A>It is the first of these that is the real problem.  When using other features of C++ such as classes, overloaded operators, virtual functions, or templates, it may be difficult to write the code correctly in the first place, but once written it is easy to use from then on.  Exceptions go against this trend.  Throwing an exception is easy; writing the code that uses the function that throws the exception is the hard part.  Every function that can have an exception propagate out of it must be designed to propagate that exception correctly.  As Tom Cargill says in <A HREF="#ref1" ONMOUSEOVER = "self.status = 'Reference 1'; return true" ONMOUSEOUT = "self.status = self.defaultStatus">Reference 1</A>, &quot;The really hard part of using exceptions is to write all the intervening code in such a way that an arbitrary exception can propagate from its throw site to its handler, arriving safely and without damaging other parts of the program along the <NOBR>way.&quot;<SCRIPT>create_link(8);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp9"></A><A NAME="AUTO00005"></A>Of course, it is (ii) and (iii) that make writing all that intervening code difficult. Consider the apparent asynchronous nature of exceptions (exceptions are not truly asynchronous events like a network driver interrupt, but from the outside, they can have almost the same effect). The following <NOBR>statement:<SCRIPT>create_link(9);</SCRIPT>
</NOBR></P>

<A NAME="AUTO00147"></A><UL><PRE>
while (*i++ = *j++) ;
</PRE>
</UL>

<P><A NAME="dingp10"></A><A NAME="AUTO00006"></A>is a typical C idiom that has been carried over (with some major extensions) into C++.  In fact, one can almost say that the <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=stltutorial" ONMOUSEOVER = "self.status = 'Standard Template Library'; return true" ONMOUSEOUT = "self.status = self.defaultStatus" TARGET="_top">Standard</NOBR> Template Library</A> was designed around such idioms.  In C++, <CODE>i</CODE> and <CODE>j</CODE> can be two different, user-defined iterator types. Assume that <CODE>i</CODE> iterates over a container of A objects, and <CODE>j</CODE> iterates over a container of B objects. Let's let a represent <CODE>*i</CODE> and b represent <CODE>*j</CODE>. Assignment will have been overridden if A is a user defined type, but it may not be defined specifically for the type represented by B, necessitating invocation of a user-defined conversion function. Another user-defined conversion function may have to be invoked to convert the result of the assignment statement into something that can be converted to type <CODE>bool</CODE> for the &quot;while&quot; condition.  Any of these user defined operators or conversions might throw an exception &#151; or any of the functions that they invoke, and so on.  If an exception occurs in this statement, the user may have no idea where it came from.  More importantly, the order of evaluation of several parts of the above expression is unspecified.  Therefore, if an exception appears, the user may have a hard time determining the current state of <CODE>i</CODE>, <CODE>j</CODE>, <CODE>a</CODE>, or <CODE>b</CODE>.<SCRIPT>create_link(10);</SCRIPT>
</P>

<A NAME="AUTO00007"></A>

<P><A NAME="dingp11"></A><I>Finally</I>, as noted in (iii), exceptions can not be ignored.  With older error reporting techniques, nothing but discipline forced the programmer to check the return value or error code.  Even if you knew errors were possible, you did not have to check the return value immediately, just as long as it was checked before it mattered.  With exceptions, this is no longer possible.  You have to cope with an exception when and where it occurs, not when and where it is convenient for you.  This is true even if you do not plan to actually handle the <NOBR>exception.<SCRIPT>create_link(11);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp12"></A><A NAME="AUTO00008"></A>So, I have concluded that using exceptions effectively is going to be difficult.  Nevertheless, I have also considered the alternatives.  Without exceptions it is impossible to return an error from a constructor or an overloaded operator.  This situation has lead to several ad-hoc schemes.  A couple of the more popular ones <NOBR>are:<SCRIPT>create_link(12);</SCRIPT>
</NOBR></P>

<UL>
<A NAME="dingp13"></A><LI><I>Set an internal error flag.</I>  An <CODE>operator!</CODE> function or a conversion to <CODE>bool</CODE> or<CODE> void*</CODE> is often provided to simplify testing the state of the object.  Such a scheme can be used to tell if a constructor (or an operator) succeeded or failed, but it does not tell anything about why the failure occurred.  For that, a member function that returns the value of an error code is usually provided.<SCRIPT>create_link(13);</SCRIPT>

<A NAME="AUTO00009"></A>
<A NAME="dingp14"></A><LI><I>Two-stage construction.</I>  In this scheme, the actual object constructor only initializes memory.  A second &quot;initialization&quot; function is called after an object is 'constructed' to do resource allocation and any other complex operations that might encounter errors.  This scheme does provide a means to return error indications to the user, but the user has to know about the need to initialize the object before it can be used.  It does not work with overload operators.<SCRIPT>create_link(14);</SCRIPT>


</UL>

<P><A NAME="dingp15"></A><A NAME="AUTO00010"></A>Since there is no standardization for any of this, it is difficult to combine libraries that use slightly different techniques.  It also is virtually impossible to use such classes to instantiate general purpose templates like those that are now part of the <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=cstandard" ONMOUSEOVER = "self.status = 'Standard C++ Library'; return true" ONMOUSEOUT = "self.status = self.defaultStatus" TARGET="_top">Standard</NOBR> C++ Library</A>. The truth is: without exceptions, a lot of the features that make C++ so powerful &#151; constructors, overloaded operators, and templates &#151; are either not as robust as we need them to be, or simply can not be used in situations where good error handling is <NOBR>required.<SCRIPT>create_link(15);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp16"></A><A NAME="AUTO000101"></A>What follows are some goals and guidelines that I have put together on how to cope with exceptions.  The &quot;goals&quot; are general, high level concepts. Meeting a &quot;goal&quot; may involve re-writing a function or major changes to a class library.  The &quot;guidelines&quot; are more specific, lower level concepts that can often be applied to help meet the goals.  As with most such offerings, every user will have to evaluate their own circumstances and determine which of these goals and guidelines are applicable to their situation.  In many cases, I have found that exceptions are already approaching the status of religion.  Under the circumstances, I try to offer reasonable explanations for my recommendations.  Nevertheless, my
ultimate goal is more reliable software, not religious discussions.  If
other approaches work for you, by all means use them.  I would like to hear
from readers who have applied these and other guidelines on real projects
&#151; successfully or not.  The more collective knowledge we can build on this topic, the better off we will all <NOBR>be.<SCRIPT>create_link(16);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp17"></A><FONT ID="aititle">Terminology and Conventions</FONT><SCRIPT>create_link(17);</SCRIPT>
</P>

<P><A NAME="dingp18"></A><A NAME="AUTO000102"></A>In the following, I often mention the &quot;state of an object&quot;.  In <A HREF="#ref2" ONMOUSEOVER = "self.status = 'Reference 2'; return true" ONMOUSEOUT = "self.status = self.defaultStatus">Reference 2</A>, Dr. Harald M&uuml;ller presents a more general discussion of the problems I discuss in goals <A HREF="#goal1" ONMOUSEOVER = "self.status = 'goals discussion I'; return true" ONMOUSEOUT = "self.status = self.defaultStatus">I</A> through <A HREF="#goal3" ONMOUSEOVER = "self.status = 'goals discussion III'; return true" ONMOUSEOUT = "self.status = self.defaultStatus">III</A>.  In his article, Dr. M&uuml;ller talks about &quot;resources&quot;.  I have decided to stick with the term &quot;object&quot; since that is the type of resource most C++ programmers are going to be concerned with most often (I do use the term &quot;resource leak&quot;).  In Dr. M&uuml;ller's article, he defines and discusses how resources can be in either &quot;good&quot; or &quot;bad&quot; states.  While my concepts are similar, I prefer slightly different terminology than Dr. M&uuml;ller.  In simple terms, an object can be in one of the following <NOBR>states:<SCRIPT>create_link(18);</SCRIPT>
</NOBR></P>

<UL>
<A NAME="AUTO000103"></A>
<A NAME="dingp19"></A><LI><I>Good</I> - an object is in a good state when its member variables are consistent relative to each other and the object represents a valid data element of the abstract type that it is modeling.<SCRIPT>create_link(19);</SCRIPT>

<A NAME="AUTO00011"></A>
<A NAME="dingp20"></A><LI><I>Bad</I> - an object is in a bad state if it somehow becomes inconsistent internally or no longer represents a valid abstract data element.  When a object is in a bad state, certain operations on that object will no longer work properly; other operations may continue to work. Most especially, according to my usage, when an object is in a &quot;bad&quot; state I expect the destructor to still work.  In other words, an object in a bad state is not a good object, but its state is still well defined enough to allow the program to continue.<SCRIPT>create_link(20);</SCRIPT>

<A NAME="AUTO00012"></A>
<A NAME="dingp21"></A><LI><I>Undefined</I> - an object in an undefined state has been corrupted to the point where it can not even be safely destroyed.  When an object is in an undefined state nothing is guaranteed to work, and something catastrophic is probably going to happen if any attempt is made to use the object (e.g. a process abort).<SCRIPT>create_link(21);</SCRIPT>


</UL>

<P><A NAME="dingp22"></A>My definitions correspond fairly closely with Dr. M&uuml;ller's as <NOBR>follows:<SCRIPT>create_link(22);</SCRIPT>
</NOBR></P>
<A NAME="AUTO00013"></A>

<TABLE ALIGN="center" WIDTH="80%" CELLSPACING="3" CELLPADDING="3">
<TR><TH BGCOLOR="#000000"><FONT COLOR="#FFFFFF">Dr. M&uuml;ller</FONT></TH><TH BGCOLOR="#000000"><FONT COLOR="#FFFFFF">Mine</FONT></TH></TR>
<TR><TD BGCOLOR="#FFFFCC">good</TD><TD BGCOLOR="#FFFFCC">good</TD></TR>
<TR><TD BGCOLOR="#FFFFCC">bad (valid shut-down)</TD><TD BGCOLOR="#FFFFCC">bad</TD></TR>
<TR><TD BGCOLOR="#FFFFCC">bad (not a shut-down)</TD><TD BGCOLOR="#FFFFCC">undefined</TD></TR>
</TABLE>

⌨️ 快捷键说明

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