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

📄 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 页
字号:
<font color=#0000ff>public</font>:
  UseResources(<font color=#0000ff>int</font> count = 1) {
    out &lt;&lt; <font color=#004488>"UseResources()"</font> &lt;&lt; endl;
    bp = <font color=#0000ff>new</font> Cat[count];
    op = <font color=#0000ff>new</font> Dog;
  }
  ~UseResources() {
    out &lt;&lt; <font color=#004488>"~UseResources()"</font> &lt;&lt; endl;
    <font color=#0000ff>delete</font> []bp; <font color=#009900>// Array delete</font>
    <font color=#0000ff>delete</font> op;
  }
};

<font color=#0000ff>int</font> main() {
  <font color=#0000ff>try</font> {
    UseResources ur(3);
  } <font color=#0000ff>catch</font>(<font color=#0000ff>int</font>) {
    out &lt;&lt; <font color=#004488>"inside handler"</font> &lt;&lt; endl;
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The output is the
following:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>UseResources()
Cat()
Cat()
Cat()
allocating a Dog
inside handler</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>UseResources</B> constructor is
entered, and the <B>Cat</B> constructor is successfully completed for the array
objects. However, inside <B>Dog::operator new</B>, an exception is thrown (as an
example of an out-of-memory error). Suddenly, you end up inside the handler,
<I>without</I> the <B>UseResources</B> destructor being called. This is correct
because the <B>UseResources</B> constructor was unable to finish, but it means
the <B>Cat</B> object that was successfully created on the heap is never
destroyed.</FONT><A NAME="_Toc312374123"></A><A NAME="_Toc519041893"></A><BR></P></DIV>
<A NAME="Heading37"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Making everything an object</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To prevent this, guard against these
&#8220;raw&#8221; resource allocations by placing the allocations inside their
own objects with their own constructors and destructors. This way, each
allocation becomes atomic<A NAME="Index77"></A>, as an object, and if it fails,
the other resource allocation objects are properly cleaned up. Templates are an
excellent way to modify the above example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C01:Wrapped.cpp</font>
<font color=#009900>// Safe, atomic pointers</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;fstream&gt;
#include &lt;cstdlib&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
ofstream out(<font color=#004488>"wrapped.out"</font>);

<font color=#009900>// Simplified. Yours may have other arguments.</font>
<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> T, <font color=#0000ff>int</font> sz = 1&gt; <font color=#0000ff>class</font> PWrap {
  T* ptr;
<font color=#0000ff>public</font>:
  <font color=#0000ff>class</font> RangeError {}; <font color=#009900>// Exception class</font>
  PWrap() {
    ptr = <font color=#0000ff>new</font> T[sz];
    out &lt;&lt; <font color=#004488>"PWrap constructor"</font> &lt;&lt; endl;
  }
  ~PWrap() {
    <font color=#0000ff>delete</font> []ptr;
    out &lt;&lt; <font color=#004488>"PWrap destructor"</font> &lt;&lt; endl;
  }
  T&amp; <font color=#0000ff>operator</font>[](<font color=#0000ff>int</font> i) <font color=#0000ff>throw</font>(RangeError) {
    <font color=#0000ff>if</font>(i &gt;= 0 &amp;&amp; i &lt; sz) <font color=#0000ff>return</font> ptr[i];
    <font color=#0000ff>throw</font> RangeError();
  }
};

<font color=#0000ff>class</font> Cat {
<font color=#0000ff>public</font>:
  Cat() { out &lt;&lt; <font color=#004488>"Cat()"</font> &lt;&lt; endl; }
  ~Cat() { out &lt;&lt; <font color=#004488>"~Cat()"</font> &lt;&lt; endl; }
  <font color=#0000ff>void</font> g() {}
};

<font color=#0000ff>class</font> Dog {
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font>* <font color=#0000ff>operator</font> <font color=#0000ff>new</font>[](size_t sz) {
    out &lt;&lt; <font color=#004488>"allocating an Dog"</font> &lt;&lt; endl;
    <font color=#0000ff>throw</font> <font color=#0000ff>int</font>(47);
  }
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font> <font color=#0000ff>delete</font>[](<font color=#0000ff>void</font>* p) {
    out &lt;&lt; <font color=#004488>"deallocating an Dog"</font> &lt;&lt; endl;
    ::<font color=#0000ff>delete</font> p;
  }
};

<font color=#0000ff>class</font> UseResources {
  PWrap&lt;Cat, 3&gt; Bonk;
  PWrap&lt;Dog&gt; Og;
<font color=#0000ff>public</font>:
  UseResources() : Bonk(), Og() {
    out &lt;&lt; <font color=#004488>"UseResources()"</font> &lt;&lt; endl;
  }
  ~UseResources() {
    out &lt;&lt; <font color=#004488>"~UseResources()"</font> &lt;&lt; endl;
  }
  <font color=#0000ff>void</font> f() { Bonk[1].g(); }
};

<font color=#0000ff>int</font> main() {
  <font color=#0000ff>try</font> {
    UseResources ur;
  } <font color=#0000ff>catch</font>(<font color=#0000ff>int</font>) {
    out &lt;&lt; <font color=#004488>"inside handler"</font> &lt;&lt; endl;
  } <font color=#0000ff>catch</font>(...) {
    out &lt;&lt; <font color=#004488>"inside catch(...)"</font> &lt;&lt; endl;
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The difference is the use of the template
to wrap the pointers and make them into objects. The constructors for these
objects are called <I>before</I> the body of the <B>UseResources</B>
constructor, and any of these constructors that complete before an exception is
thrown will have their associated destructors called.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>PWrap</B> template shows a more
typical use of exceptions than you&#8217;ve seen so far: A nested class called
<B>RangeError</B> is created to use in <B>operator[ ]<A NAME="Index78"></A></B>
if its argument is out of range. Because <B>operator[ ]</B> returns a
reference<A NAME="Index79"></A><A NAME="Index80"></A> it cannot return zero.
(There are no null references.) This is a true exceptional condition &#8211; you
don&#8217;t know what to do in the current context, and you can&#8217;t return
an improbable value. In this example, <B>RangeError</B> is very simple and
assumes all the necessary information is in the class name, but you may also
want to add a member that contains the value of the index, if that is
useful.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now the output is</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Cat()
Cat()
Cat()
PWrap constructor
allocating a Dog
~Cat()
~Cat()
~Cat()
PWrap destructor
inside handler</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Again, the storage allocation for
<B>Dog</B> throws an exception, but this time the array of <B>Cat</B> objects is
properly cleaned up, so there is no memory
leak.</FONT><A NAME="_Toc305593301"></A><A NAME="_Toc305628773"></A><A NAME="_Toc312374124"></A><A NAME="_Toc519041894"></A><BR></P></DIV>
<A NAME="Heading38"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Exception matching<BR><A NAME="Index81"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When an exception is thrown, the
exception-handling system looks through the &#8220;nearest&#8221; handlers in
the order they are written. When it finds a match, the exception is considered
handled, and no further searching occurs. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Matching an exception doesn&#8217;t
require a perfect match between the exception and its handler. An object or
reference to a derived-class object will match a handler for the base class.
(However, if the handler is for an object rather than a reference, the exception
object is &#8220;sliced&#8221;
<A NAME="Index82"></A><A NAME="Index83"></A><A NAME="Index84"></A>as it is
passed to the handler; this does no damage but loses all the derived-type
information.) If a pointer is thrown, standard pointer conversions are used to
match the exception. However, no automatic type conversions
<A NAME="Index85"></A><A NAME="Index86"></A><A NAME="Index87"></A><A NAME="Index88"></A>are
used to convert one exception type to another in the process of matching. For
example,</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C01:Autoexcp.cpp</font>
<font color=#009900>// No matching conversions</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Except1 {};
<font color=#0000ff>class</font> Except2 {
<font color=#0000ff>public</font>:
  Except2(Except1&amp;) {}
};

<font color=#0000ff>void</font> f() { <font color=#0000ff>throw</font> Except1(); }

<font color=#0000ff>int</font> main() {
  <font color=#0000ff>try</font> { f();
  } <font color=#0000ff>catch</font> (Except2) {
    cout &lt;&lt; <font color=#004488>"inside catch(Except2)"</font> &lt;&lt; endl;
  } <font color=#0000ff>catch</font> (Except1) {
    cout &lt;&lt; <font color=#004488>"inside catch(Except1)"</font> &lt;&lt; endl;
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Even though you might think the first
handler could be used by converting an <B>Except1</B> object into an
<B>Except2</B> using the constructor conversion, the system will not perform
such a conversion during exception handling, and you&#8217;ll end up at the
<B>Except1</B> handler.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index89"></A><A NAME="Index90"></A><FONT FACE="Georgia">The
following example shows how a base-class handler can catch a derived-class
exception:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C01:Basexcpt.cpp</font>
<font color=#009900>// Exception hierarchies</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> X {
<font color=#0000ff>public</font>:
  <font color=#0000ff>class</font> Trouble {};
  <font color=#0000ff>class</font> Small : <font color=#0000ff>public</font> Trouble {};
  <font color=#0000ff>class</font> Big : <font color=#0000ff>public</font> Trouble {};
  <font color=#0000ff>void</font> f() { <font color=#0000ff>throw</font> Big(); }
};

<font color=#0000ff>int</font> main() {
  X x;
  <font color=#0000ff>try</font> {
    x.f();
  } <font color=#0000ff>catch</font>(X::Trouble) {
    cout &lt;&lt; <font color=#004488>"caught Trouble"</font> &lt;&lt; endl;
  <font color=#009900>// Hidden by previous handler:</font>

⌨️ 快捷键说明

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