📄 ch26.htm
字号:
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> catch (MyException e)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> </font><font color="#008000">delete floatarray;</font></pre>
<pre><font color="#008000"> </font><font color="#008000">throw;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> delete floatarray;</font></pre>
<pre><font color="#008000"> return retval; </font></pre>
<pre><font color="#008000">}</font></pre>
<P>This revised version <font color="#008000">of Intermediate()</font> catches the exception just so that it can <font color="#008000">delete</font> <font color="#008000">floatarray</font>, and then throws it further up to the calling function. (Notice
that the name of the exception is not in this throw statement: it can throw only the exception it just caught.) There are a few things you should notice about this revised code:</P>
<ul>
<li> The line that deletes <font color="#008000">floatarray</font> has been duplicated. </P>
<li> The declaration of <font color="#008000">retval</font> has had to move out of the <font color="#008000">try</font> block so that it will still be in scope after the <font color="#008000">try</font> block. </P>
<li> <font color="#008000">retval</font> has been initialized to a default value.</P>
</ul>
<P>This is really starting to get ugly. Through all of this, the <font color="#008000">BigObject</font> called <font color="#008000">bigarray</font> has been quietly handled properly and easily, with an automatic call to the destructor no matter which
function allocated it or where the exception was called. When you write code that uses exceptions, wrapping all your heap-allocated objects in classes like <font color="#008000">BigObject</font> makes your life easier. <font
color="#008000">BigObject</font> implements a <I>managed </I><I>pointer</I>: when a <font color="#008000">BigObject</font> object like <font color="#008000">bigarray</font> goes out of scope, the memory it pointed to is deleted. A very flexible approach to
managed pointers is described at the end of the Template section in this chapter.</P>
<P><B> Handling Multiple Types of Exceptions</B></P>
<P>Because it's often the case that a block of code generates more than one type of exception, you can use multiple <font color="#008000">catch</font> blocks with a <font color="#008000">try</font> block. You might, for example, need to be on the lookout
for both <font color="#008000">CException</font> and <font color="#008000">char*</font> exceptions. Because a <font color="#008000">catch</font> block must receive a specific type of exception object, you need two different <font
color="#008000">catch</font> blocks to watch for both <font color="#008000">CException</font> and <font color="#008000">char*</font> exception objects. You can also set up a catch block to catch whatever type of exception hasn't been caught yet, by placing
ellipses (...) in the parentheses, rather than a specific argument. The problem with this sort of multipurpose <font color="#008000">catch</font> block is that you have no access to the exception object received and so must handle the exception in some
general way.</P>
<P>Listing 26.6 is a program that generates three different types of exceptions based on a user's input. (In a real program, you shouldn't use exceptions to deal with user errors. It's a slow mechanism, and checking what the user typed can usually be
handled more efficiently another way.)</P>
<P>When you run the program, you're instructed to enter a value between 4 and 8, except for 6. If you enter a value less than 4, the program throws a <font color="#008000">MyException</font> exception; if you enter a value greater than 8, the program
throws a <font color="#008000">char*</font> exception; and, finally, if you happen to enter 6, the program throws the entered value as an exception.</P>
<P>Although the program throws the exceptions in the <font color="#008000">GetValue()</font> function, the program catches them all in <font color="#008000">main()</font>. The <font color="#008000">try</font> block in <font color="#008000">main()</font>
is associated with three <font color="#008000">catch</font> blocks. The first catches the <font color="#008000">MyException</font> object, the second catches the <font color="#008000">char*</font> object, and the third catches any other exception that
happens to come down the pike.</P>
<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">
<P>Just as with <font color="#008000">if-else</font> statements, the order in which you place <font color="#008000">catch</font> program blocks can have a profound effect on program execution. You should always place the most specific <font
color="#008000">catch</font> blocks first. For example, in Listing 26.6, if the <font color="#008000">catch(</font><font color="#008000">...</font><font color="#008000">)</font> block was first, none of the other <font color="#008000">catch</font> blocks
would ever be called. This is because the <font color="#008000">catch(</font><font color="#008000">...</font><font color="#008000">)</font> is as general as you can get, catching every single exception that the program throws. In this case (as in most
cases), you want to use <font color="#008000">catch(</font><font color="#008000">...</font><font color="#008000">)</font> to receive only the leftover exceptions.</P>
<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>
<P><I>Listing 26.6—EXCEPTION6.CPP—Using Multiple </I>catch<I> Blocks</I></P>
<pre><font color="#008000">#include <iostream.h></font></pre>
<pre><font color="#008000">class MyException</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000">protected:</font></pre>
<pre><font color="#008000"> char* m_msg;</font></pre>
<pre><font color="#008000">public:</font></pre>
<pre><font color="#008000"> MyException(char *msg) { m_msg = msg;}</font></pre>
<pre><font color="#008000"> ~MyException(){}</font></pre>
<pre><font color="#008000"> char* GetError() {return m_msg;}</font></pre>
<pre><font color="#008000">};</font></pre>
<pre><font color="#008000">int GetValue();</font></pre>
<pre><font color="#008000">int main()</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> try</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> int value = GetValue();</font></pre>
<pre><font color="#008000"> cout << "The value you entered is okay." << endl;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> catch(MyException* exception)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> char* msg = exception->GetError();</font></pre>
<pre><font color="#008000"> cout << msg << endl;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> catch(char* msg)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> cout << msg << endl;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> catch(...)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> cout << "Caught unknown exception!" << endl;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> return 0;</font></pre>
<pre><font color="#008000">}</font></pre>
<pre><font color="#008000">int GetValue(){</font></pre>
<pre><font color="#008000"> int value;</font></pre>
<pre><font color="#008000"> cout << "Type a number from 4 to 8 (except 6):" << endl;</font></pre>
<pre><font color="#008000"> cin >> value;</font></pre>
<pre><font color="#008000"> if (value < 4)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> MyException* exception =</font></pre>
<pre><font color="#008000"> new MyException("Value less than 4!");</font></pre>
<pre><font color="#008000"> throw exception;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> else if (value > 8)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> throw "Value greater than 8!";</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> else if (value == 6)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> throw value;</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> return value;</font></pre>
<pre><font color="#008000">}</font></pre>
<P><B>The Old Exception Mechanism</B></P>
<P>Before try, catch, and throw were added to Visual C++, there was a rudimentary form of exception handling available to both C and C++ programmers through macros called TRY, CATCH, and THROW. These macros are a little slower than the standard exception
mechanisms, and can only throw exceptions that are objects of a class derived from <font color="#008000">CException</font>. Don't use these in your programs. If you have an existing program that uses them, you may want to convert to the new mechanism.
There's a helpful article on this topic in the Visual C++ documentation: search for TRY and you'll find it.</P>
<H3>Exploring Templates</H3>
<P>It's a good guess that, at one time or another, you wished you could develop a single function or class that could handle any kind of data. Sure, you can use function overloading to write several versions of a function, or you can use inheritance to
derive several different classes from a base class. But, in these cases, you still end up writing many different functions or classes. If only there was a way to make functions and classes a little smarter, so that you could write just one that handled any
kind of data you wanted to throw at it. There is a way to accomplish this seemingly impossible task. You need to use something called <I>templates,</I> which are the focus of this section.</P>
<P><B>Introducing Templates</B></P>
<P>A <I>template</I> is a kind of blueprint for a function or class. You write the template in a general way, supplying placeholders, called <I>parameters</I>, for the data objects that the final function or class will manipulate. A template always begins
with the keyword <font color="#008000">template</font> followed by a list of parameters between angle brackets, like this:</P>
<pre><font color="#008000">template<class Type></font></pre>
<P>You can have as many parameters as you need, and you can name them whatever you like, but each must begin with the <font color="#008000">class</font> keyword and must be separated by commas, like this:</P>
<pre><font color="#008000">template<class Type1, class Type2, class Type3></font></pre>
<P>As you may have guessed from the previous discussion, there are two types of templates: function and class. The following sections describe how to create and use both types of templates.</P>
<P><B>Creating Function Templates</B></P>
<P>A function template starts with the <font color="#008000">template</font> line you just learned about, followed by the function's declaration, as shown in Listing 26.7. The <font color="#008000">template</font> line specifies the types of arguments
that will be used when calling the function, whereas the function's declaration specifies how those arguments are to be received as parameters by the function. Every parameter specified in the <font color="#008000">template</font> line must be used by the
function declaration. Notice the <font color="#008000">Type1</font> immediately before the function name. <font color="#008000">Type1</font> is a placeholder for the function's return type, which will vary depending upon how the template is used.</P>
<P><I>Listing 26.7— The Basic Form of a Function Template</I></P>
<pre><font color="#008000">template<class Type1, class Type2></font></pre>
<pre><font color="#008000">Type1 MyFunction(Type1 data1, Type1 data2, Type2 data3)</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> // Place the body of the function here.</font></pre>
<pre><font color="#008000">}</font></pre>
<P>An actual working example will help you understand how function templates become functions. A common example is a <font color="#008000">Min()</font> function that can accept any type of arguments. Listing 26.6 is a short program that defines a template
for a <font color="#008000">Min()</font> function and then uses that function in <font color="#008000">main()</font>. When you run the program, the program displays the smallest value of whatever data is sent as arguments to <font
color="#008000">Min()</font>. This works because the compiler takes the template and creates functions for each of the data types that are compared in the program.</P>
<P><I>Listing 26.8—TEMPLATE1.CPP—Using a Typical Function Template</I></P>
<pre><font color="#008000">#include <iostream.h></font></pre>
<pre><font color="#008000">template<class Type></font></pre>
<pre><font color="#008000">Type Min(Type arg1, Type arg2)</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> Type min;</font></pre>
<pre><font color="#008000"> if (arg1 < arg2)</font></pre>
<pre><font color="#008000"> min = arg1;</font></pre>
<pre><font color="#008000"> else</font></pre>
<pre><font color="#008000"> min = arg2;</font></pre>
<pre><font color="#008000"> return min;</font></pre>
<pre><font color="#008000">}</font></pre>
<pre><font color="#008000">int main()</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> cout << Min(15, 25) << endl;</font></pre>
<pre><font color="#008000"> cout << Min(254.78, 12.983) << endl;</font></pre>
<pre><font color="#008000"> cout << Min('A', 'Z') << endl;</font></pre>
<pre><font color="#008000"> return 0;</font></pre>
<pre><font color="#008000">}</font></pre>
<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">
<P>Notice how, in Listing 26.8, the <font color="#008000">Min()</font> template uses the data type <font color="#008000">Type</font> not only in its parameter list and function argument list, but also in the body of the function, in order to declare a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -