📄 ch20.htm
字号:
54: pType[i] = rhs[i];
55: }
56: template <class T>
57: Array<T>::Array(const Array<T> &rhs)
58: {
59: itsSize = rhs.GetitsSize();
60: pType = new T[itsSize];
61: for (int i = 0; i<itsSize; i++)
62: pType[i] = rhs[i];
63: }
64:
65: template <class T>
66: T& Array<T>::operator[](int offSet)
67: {
68: int size = GetitsSize();
69: if (offSet >= 0 && offSet < GetitsSize())
70: return pType[offSet];
71: throw xBoundary();
72: return pType[0];
73: }
74:
75: template <class T>
76: const T& Array<T>::operator[](int offSet) const
77: {
78: int mysize = GetitsSize();
79: if (offSet >= 0 && offSet < GetitsSize())
80: return pType[offSet];
81: throw xBoundary();
82: }
83:
84: template <class T>
85: ostream& operator<< (ostream& output, const Array<T>& theArray)
86: {
87: for (int i = 0; i<theArray.GetitsSize(); i++)
88: output << "[" << i << "] " << theArray[i] << endl;
89: return output;
90: }
91:
92:
93: int main()
94: {
95:
96: try
97: {
98: Array<int> intArray(9);
99: for (int j = 0; j< 100; j++)
100: {
101: intArray[j] = j;
102: cout << "intArray[" << j << "] okay..." << endl;
103: }
104: }
105: catch (xBoundary)
106: {
107: cout << "Unable to process your input!\n";
108: }
109: catch (Array<int>::xSize)
110: {
111: cout << "Bad Size!\n";
112: }
113:
114: cout << "Done.\n";
115: return 0;
<TT>116: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: Bad Size!
Done.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The first exception, <TT>xBoundary</TT>,
is declared outside the template definition on line 3. The second exception, <TT>xSize</TT>,
is declared from within the definition of the template, on line 27.<BR>
<BR>
The exception <TT>xBoundary</TT> is not tied to the <TT>template</TT> class, but
can be used like any other class. <TT>xSize</TT> is tied to the template, and must
be called based on the instantiated <TT>Array</TT>. You can see the difference in
the syntax for the two <TT>catch</TT> statements. Line 105 shows <TT>catch (xBoundary)</TT>,
but line 109 shows <TT>catch (Array<int>::xSize)</TT>. The latter is tied to
the instantiation of an integer <TT>Array</TT>.
<H3 ALIGN="CENTER"><A NAME="Heading25"></A><FONT COLOR="#000077">Exceptions Without
Errors</FONT></H3>
<P>When C++ programmers get together for a virtual beer in the cyberspace bar after
work, talk often turns to whether exceptions should be used for routine conditions.
Some maintain that by their nature, exceptions should be reserved for those predictable
but exceptional circumstances (hence the name!) that a programmer must anticipate,
but that are not part of the routine processing of the code.</P>
<P>Others point out that exceptions offer a powerful and clean way to return through
many layers of function calls without danger of memory leaks. A frequent example
is this: The user requests an action in a GUI environment. The part of the code that
catches the request must call a member function on a dialog manager, which in turn
calls code that processes the request, which calls code that decides which dialog
box to use, which in turn calls code to put up the dialog box, which finally calls
code that processes the user's input. If the user presses Cancel, the code must return
to the very first calling method, where the original request was handled.</P>
<P>One approach to this problem is to put a <TT>try</TT> block around the original
call and catch <TT>CancelDialog</TT> as an exception, which can be raised by the
handler for the Cancel button. This is safe and effective, but pressing Cancel is
a routine circumstance, not an exceptional one.</P>
<P>This frequently becomes something of a religious argument, but there is a reasonable
way to decide the question: Does use of exceptions in this way make the code easier
or harder to understand? Are there fewer risks of errors and memory leaks, or more?
Will it be harder or easier to maintain this code? These decisions, like so many
others, will require an analysis of the trade-offs; there is no single, obvious right
answer.
<H3 ALIGN="CENTER"><A NAME="Heading26"></A><FONT COLOR="#000077">Bugs and Debugging</FONT></H3>
<P>You saw on Day 17 how to use <TT>assert()</TT> to trap runtime bugs during the
testing phase, and today you saw how to use exceptions to trap runtime problems.
There is one more powerful weapon you'll want to add to your arsenal as you attack
bugs: the debugger.</P>
<P>Nearly all modern development environments include one or more high-powered debuggers.
The essential idea of using a debugger is this: You run the debugger, which loads
your source code, and then you run your program from within the debugger. This allows
you to see each instruction in your program as it executes, and to examine your variables
as they change during the life of your program.</P>
<P>All compilers will let you compile with or without symbols. Compiling with symbols
tells the compiler to create the necessary mapping between your source code and the
generated program; the debugger uses this to point to the line of source code that
corresponds to the next action in the program.</P>
<P>Full-screen symbolic debuggers make this chore a delight. When you load your debugger,
it will read through all your source code and show the code in a window. You can
step over function calls or direct the debugger to step into the function, line by
line.</P>
<P>With most debuggers, you can switch between the source code and the output to
see the results of each executed statement. More powerfully, you can examine the
current state of each variable, look at complex data structures, examine the value
of member data within classes, and look at the actual values in memory of various
pointers and other memory locations. You can execute several types of control within
a debugger that include setting breakpoints, setting watch points, examining memory,
and looking at the assembler code.
<H4 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">Breakpoints</FONT></H4>
<P>Breakpoints are instructions to the debugger that when a particular line of code
is ready to be executed, the program should stop. This allows you to run your program
unimpeded until the line in question is reached. Breakpoints help you analyze the
current condition of variables just before and after a critical line of code.
<H4 ALIGN="CENTER"><A NAME="Heading28"></A><FONT COLOR="#000077">Watch Points</FONT></H4>
<P>It is possible to tell the debugger to show you the value of a particular variable
or to break when a particular variable is read or written to. Watch points allow
you to set these conditions, and at times even to modify the value of a variable
while the program is running.
<H4 ALIGN="CENTER"><A NAME="Heading29"></A><FONT COLOR="#000077">Examining Memory</FONT></H4>
<P>At times it is important to see the actual values held in memory. Modern debuggers
can show values in the form of the actual variable; that is, strings can be shown
as characters, <TT>long</TT>s as numbers rather than as four bytes, and so forth.
Sophisticated C++ debuggers can even show complete classes, providing the current
value of all the member variables, including the <TT>this</TT> pointer.
<H4 ALIGN="CENTER"><A NAME="Heading30"></A><FONT COLOR="#000077">Assembler</FONT></H4>
<P>Although reading through the source can be all that is required to find a bug,
when all else fails it is possible to instruct the debugger to show you the actual
assembly code generated for each line of your source code. You can examine the memory
registers and flags, and generally delve as deep into the inner workings of your
program as required.</P>
<P>Learn to use your debugger. It can be the most powerful weapon in your holy war
against bugs. Runtime bugs are the hardest to find and squash, and a powerful debugger
can make it possible, if not easy, to find nearly all of them.
<H3 ALIGN="CENTER"><A NAME="Heading31"></A><FONT COLOR="#000077">Summary</FONT></H3>
<P>Today you learned how to create and use exceptions. Exceptions are objects that
can be created and thrown at points in the program where the executing code cannot
handle the error or other exceptional condition that has arisen. Other parts of the
program, higher in the call stack, implement <TT>catch</TT> blocks that catch the
exception and take appropriate action.</P>
<P>Exceptions are normal, user-created objects, and as such may be passed by value
or by reference. They may contain data and methods, and the <TT>catch</TT> block
may use that data to decide how to deal with the exception.</P>
<P>It is possible to create multiple <TT>catch</TT> blocks, but once an exception
matches a <TT>catch</TT> block's signature, it is considered to be handled and is
not given to the subsequent <TT>catch</TT> blocks. It is important to order the <TT>catch</TT>
blocks appropriately, so that more specific <TT>catch</TT> blocks have first chance
and more general <TT>catch</TT> blocks handle those not otherwise handled.</P>
<P>This chapter also examined some of the fundamentals of symbolic debuggers, including
using watch points, breakpoints, and so forth. These tools can help you zero in on
the part of your program that is causing the error, and let you see the value of
variables as they change during the course of the execution of the program.
<H3 ALIGN="CENTER"><A NAME="Heading32"></A><FONT COLOR="#000077">Q&A</FONT></H3>
<DL>
<DD><B>Q. Why bother with raising exceptions? Why not handle the error right where
it happens?<BR>
</B><BR>
<B>A.</B> Often, the same error can be generated in a number of different parts of
the code. Exceptions let you centralize the handling of errors. Additionally, the
part of the code that generates the error may not be the best place to determine
how to handle the error.<BR>
<BR>
<B>Q. Why generate an object? Why not just pass an error code?<BR>
</B><BR>
<B>A.</B> Objects are more flexible and powerful than error codes. They can convey
more information, and the constructor/destructor mechanisms can be used for the creation
and removal of resources that may be required to properly handle the exceptional
condition.<BR>
<BR>
<B>Q. Why not use exceptions for non-error conditions? Isn't it convenient to be
able to express-train back to previous areas of the code, even when non-exceptional
conditions exist?</B><BR>
<BR>
<B>A.</B> Yes, some C++ programmers use exceptions for just that purpose. The danger
is that exceptions might create memory leaks as the stack is unwound and some objects
are inadvertently left in the free store. With careful programming techniques and
a good compiler, this can usually be avoided. Otherwise, it is a matter of personal
aesthetic; some programmers feel that by their nature exceptions should not be used
for routine conditions.<BR>
<BR>
<B>Q. Does an exception have to be caught in the same place where the try block created
the exception?</B><BR>
<BR>
<B>A.</B> No, it is possible to catch an exception anywhere in the call stack. As
the stack is unwound, the exception is passed up the stack until it is handled.<BR>
<BR>
<B>Q. Why use a debugger when you can use cout with conditional (#ifdef debug) compiling?<BR>
</B><BR>
<B>A.</B> The debugger provides a much more powerful mechanism for stepping through
your code and watching values change without having to clutter your code with thousands
of debugging statements.
</DL>
<H3 ALIGN="CENTER"><A NAME="Heading33"></A><FONT COLOR="#000077">Workshop</FONT></H3>
<P>The Workshop contains quiz questions to help solidify your understanding of the
material covered and exercises to provide you with experience in using what you've
learned. Try to answer the quiz and exercise questions before checking the answers
in Appendix D, and make sure you understand the answers before going to the next
chapter.
<H4 ALIGN="CENTER"><A NAME="Heading34"></A><FONT COLOR="#000077">Quiz</FONT></H4>
<DL>
<DD><B>1.</B> What is an exception?<BR>
<BR>
<B>2.</B> What is a <TT>try</TT> block?<BR>
<BR>
<B>3.</B> What is a <TT>catch</TT> statement?<BR>
<BR>
<B>4.</B> What information can an exception contain?<BR>
<BR>
<B>5.</B> When are exception objects created?<BR>
<BR>
<B>6.</B> Should you pass exceptions by value or by reference?<BR>
<BR>
<B>7.</B> Will a <TT>catch</TT> statement catch a derived exception if it is looking
for the base class?<BR>
<BR>
<B>8.</B> If there are two <TT>catch</TT> statements, one for base and one for derived,
which should come first?<BR>
<BR>
<B>9.</B> What does <TT>catch(...)</TT> mean?<BR>
<BR>
<B>10.</B> What is a breakpoint?
</DL>
<H4 ALIGN="CENTER"><A NAME="Heading35"></A><FONT COLOR="#000077">Exercises</FONT></H4>
<DL>
<DD><B>1.</B> Create a <TT>try</TT> block, a <TT>catch</TT> statement, and a simple
exception.<BR>
<BR>
<B>2.</B> Modify the answer from Exercise 1, put data into the exception, along with
an accessor function, and use it in the <TT>catch</TT> block.<BR>
<BR>
<B>3.</B> Modify the class from Exercise 2 to be a hierarchy of exceptions. Modify
the <TT>catch</TT> block to use the derived objects and the base objects.<BR>
<BR>
<B>4.</B> Modify the program from Exercise 3 to have three levels of function calls.<BR>
<BR>
<B>5.</B> BUG BUSTERS: What is wrong with the following code?
</DL>
<PRE><FONT COLOR="#0066FF">class xOutOfMemory
{
public:
xOutOfMemory( const String& message ) : itsMsg( message ){}
~xOutOfMemory(){}
virtual const String& Message(){ return itsMsg};
private:
String itsMsg;
}
main()
{
try {
char *var = new char;
if ( var == 0 )
throw xOutOfMemory();
}
catch( xOutOfMemory& theException )
{
cout << theException.Message() << "\n";
}
}
</FONT></PRE>
<P ALIGN="CENTER"><A HREF="ch19.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch19.htm"><IMG SRC="BLANPREV.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANPREV.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="tppmsgs/msgs0.htm#1" tppabs="http://www.mcp.com/sams"><IMG
SRC="BLANHOME.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANHOME.GIF" WIDTH="37" HEIGHT="37" ALIGN="BOTTOM"
BORDER="0"></A><A HREF="index.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/index.htm"><IMG SRC="BLANTOC.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANTOC.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="ch21.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch21.htm"><IMG SRC="BLANNEXT.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANNEXT.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="#heading1"><IMG SRC="BLANTOP.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANTOP.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -