📄 apd.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"><HTML><HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1"><SCRIPT LANGUAGE="JavaScript"><!--function popUp(pPage) { var fullURL = document.location; var textURL = fullURL.toString(); var URLlen = textURL.length; var lenMinusPage = textURL.lastIndexOf("/"); lenMinusPage += 1; var fullPath = textURL.substring(0,lenMinusPage); popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394'); figDoc= popUpWin.document; zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>'; zhtm += '</head>'; zhtm += '<BODY bgcolor="#FFFFFF">'; zhtm += '<IMG SRC="' + fullPath + pPage + '">'; zhtm += '<P><B>' + pPage + '</B>'; zhtm += '</BODY></HTML>'; window.popUpWin.document.write(zhtm); window.popUpWin.document.close(); // Johnny Jackson 4/28/98 }//--> </SCRIPT><link rel="stylesheet" href="/includes/stylesheets/ebooks.css"> <META NAME="GENERATOR" Content="Symantec Visual Page Mac 1.1.1"> <TITLE>Teach Yourself Visual C++ 6 in 21 Days -- Appendix D -- Understanding and Exception Handling</TITLE></HEAD><BODY TEXT="#000000" BGCOLOR="#FFFFFF"><H1 ALIGN="CENTER"><IMG SRC="../button/sams.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM"BORDER="0"><BR>Teach Yourself Visual C++ 6 in 21 Days</H1><CENTER><P><A HREF="../apc/apc.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ape/ape.htm"><IMGSRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <HR></CENTER><H1 ALIGN="CENTER">- D -<BR>Understanding and Exception Handling</H1><H1></H1><UL> <LI><A HREF="#Heading1">Using Exceptions</A> <UL> <LI><A HREF="#Heading2">Running Code and Catching the Errors</A> <LI><A HREF="#Heading3">Throwing Exceptions</A> <LI><A HREF="#Heading4">Deleting Exceptions</A> </UL> <LI><A HREF="#Heading5">MFC Exception Types</A> <UL> <LI><A HREF="#Heading6">Using the CException Base Class</A> <LI><A HREF="#Heading7">Using the Memory Exception</A> <LI><A HREF="#Heading8">Using the Resource Exceptions</A> <LI><A HREF="#Heading9">Using the File and Archive Exceptions</A> <LI><A HREF="#Heading10">Using the Database Exceptions</A> <LI><A HREF="#Heading11">Using OLE Exceptions</A> <LI><A HREF="#Heading12">Using the Not Supported Exception</A> <LI><A HREF="#Heading13">Using the User Exception</A> <LI><A HREF="#Heading14">Generating Your Own Custom Exception Classes</A> </UL></UL><P><HR SIZE="4"><BR><I>by Jon Bates</I></P><P><I></I><H2><A NAME="Heading1"></A>Using Exceptions</H2><P>An <I>exception</I> is an object that holds details about something that has gonewrong. The clever thing about exception handling is that you can create an exceptionwhen something goes wrong in a low-level function and have it automatically bubbleback up to a calling function that can deal with all such exceptions in one place.</P><P><H3><A NAME="Heading2"></A>Running Code and Catching the Errors</H3><P>The system automatically detects certain error conditions and generates exceptionsfor them. If you don't deal with them in your application, they will bubble backout of your code and be handled by Windows's own exception-catching mechanisms. Ifyou want to see this in action, just add the following two lines to any of your codeand run it:</P><P><PRE>CDC* pNullDC = 0;pNullDC->SetPixel(0,0,0);</PRE><P>The first line declares a device context pointer pNullDC and sets it to pointthe memory address to zero (which isn't a good place for any object to be). Obviouslythere isn't a valid object at this address, so when the following SetPixel() functionis called, the system tries to find the object at address zero. The memory managementhardware and software know that the program has no right being at this memory addressand raise a memory access violation exception.</P><P>If you run these lines of code from outside the Visual C++ debugger, you'll seea dialog box familiar to all Windows users, as shown in Figure D.1.</P><P><A HREF="javascript:popUp('29fig01.gif')"><B>FIGURE D.1.</B></A><B> </B><I>TheWindows memory access violation Exception dialog box.</I></P><P>However, if you run the application from the Visual C++ debugger, the debuggerfirst catches the exception for you and displays the Developer Studio dialog boxinstead, as shown in Figure D.2.</P><P><A HREF="javascript:popUp('29fig02.gif')"><B>FIGURE D.2.</B></A><B> </B><I>TheDeveloper Studio-handled memory access violation exception.</I></P><P>Memory access violations are very severe exceptions that will crash your programwithout any chance to catch them. There are many less severe exceptions, such asthe file-handling exception CFileException. This exception is thrown when erroneousfile operations occur, such as attempting to seek to the beginning of an unopenedfile:</P><P><PRE>CFile fileNotOpen;fileNotOpen.SeekToBegin();</PRE><P>This results in a system-generated dialog box (see Figure D.3). If you click OK,your program will continue as usual.</P><P><A HREF="javascript:popUp('29fig03.gif')"><B>FIGURE D.3.</B></A><B> </B><I>TheWindows default dialog box for a file exception.</I></P><P>Rather than letting the system catch the exception, you can catch the exceptionand deal with it yourself in a more graceful manner. To do this, you must use theC++ try and catch keywords. You can use these by defining a block of code to try;then, when a specified exception is raised, an action is defined in the catch block(see Listing D.1).</P><P><H4>LISTING D.1. LST29_1.CPP--USING A try AND catch BLOCK TO CATCH CFileExceptions.</H4><PRE>1: // ** Try a block of code2: try3: {4: CFile fileNotOpen;5: fileNotOpen.SeekToBegin();6: }7: catch(CFileException* e) // Catch File Exceptions8: {9: // ** Check the cause of the exception10: if (e->m_cause == CFileException::fileNotFound)11: AfxMessageBox("Oops, forgot to open the file!");12: e->Delete();13: } </PRE><P>In Listing D.1, a try block is defined around the file operations at lines 4 and5. If these lines don't raise an exception, the code will continue as normal. However,if a CFileException is raised, it will be caught by the catch keyword in line 7,and the variable e will point to the new exception. The CFileException object hasan m_cause code that defines exactly why the exception was raised. This is checkedon line 10, and if this was a CFileException::fileNotFound code, the message boxon line 11 is displayed.</P><P>Notice that the Delete() member function of the CException class (the base classof CFileException) in line 12 will delete the exception for you. You must ensurethat exceptions are always deleted when you are finished with them.</P><P>The try block can include calls to other functions and could be used to catchany specified exceptions raised in a large portion of the application, as shown inListing D.2.</P><P><H4>LISTING D.2. LST29_2.CPP--A try BLOCK CAN INCLUDE MANY FUNCTION CALLS ANDCALLS FROM THOSE FUNCTIONS.</H4><PRE>1: try2: {3: // ... Lots of code4: DoLotsOfFileHandling();5: // ... More code6: EvenMoreFileHandling();7: // ... And more Code8: }9: catch(CFileException* e) // Catch File Exceptions10: {11: // ** Check the cause of the exception12: if (e->m_cause == CFileException::fileNotFound)13: AfxMessageBox("Oops, forgot to open the file!");14: e->Delete();15: }</PRE><P>In Listing D.2 the DoLotsOfFileHandling() function on line 4 could implement somefile handling itself, as well as calls to other functions, as with EvenMoreFileHandling()on line 6. Should a file exception arise through any of these file operations, theexception will bubble back so that the same catch block will be executed in lines9 through 13 with e pointing to the CFileException object. Finally the exceptionis deleted in line 14.</P><P>If you want to catch two different exceptions from the try block, you can addcatch blocks to handle each different exception, as shown in Listing D.3.</P><P><H4>LISTING D.3. LST29_3.CPP--HANDLING TWO DIFFERENT EXCEPTIONS WITH THE EXCEPTION-SPECIFIC catch BLOCKS.</H4><PRE>1: try2: {3: // ** This file operation is ok4: CMemFile fileMemFile;5: fileMemFile.SeekToBegin();6: 7: // ** But you can't have two different system 8: // ** resources with the same name.9: CMutex mutex1(0,"Same Name");10: CSemaphore semaphore1(1,1,"Same Name");11: }12: catch(CFileException* e) // Catch File Exceptions13: {14: if (e->m_cause == CFileException::fileNotFound)15: AfxMessageBox("Oops, forgot to open the file!");16: e->Delete();17: }18: catch(CResourceException* e) Â// Catch Resource Exceptions19: {20: // ** Report the Resource exception error21: AfxMessageBox("Oops, duplicate resource name");22: e->Delete();23: } </PRE><P>In Listing D.3, the memory file is automatically created in line 4, so line 5won't cause a file exception. However, naming two different system resources (a mutexand a semaphore) with the same name does cause a CResourceException in line 10 thatis then caught by the second catch block in line 18, which displays the message boxin line 21. If you try this code yourself, remember to add an #include <afxmt.h>line for the CMutex and CSemaphore definitions.</P><P>If you want to do a blanket exception catch, you don't need to have a catch blockfor each type of exception; instead, you can catch the CException base class exceptionfrom which all the other more specific exception classes are derived (see ListingD.4).</P><P><H4>LISTING D.4. LST29_4.CPP--USING THE catch BLOCK TO CATCH ALL TYPES OF EXCEPTIONS.</H4><PRE>1: // ** Try a block of code2: try3: {4: // ** Lots of code ...5: }6: catch(CException* e)7: {8: // ** General Error message, details in e9: AfxMessageBox("Oops, something went wrong!");10: e->Delete();11: }</PRE><P>Notice that on line 6 the CException base class is used rather than a specificexception such as CFileException or CResourceException. You can test which type ofexception was raised using the IsKindOf() function inside the catch block. For example,to test whether a file exception has been raised, you might use the following lines:</P><P><PRE>if (e->IsKindOf(RUNTIME_CLASS(CFileException)))AfxMessageBox("File Exception");</PRE><P>Because exceptions are derived from CObject, they support the MFC runtime classinformation<I>.</I> By using DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC, the class informationis bundled into the derived exception object so that the IsKindOf() function canbe used to check for a specific class type. The RUNTIME_CLASS macro turns class namesinto a pointer to a CRuntimeClass object for the specified object. The IsKindOf()member function will then return TRUE if the object being called is of that runtimeclass.</P><P>The "MFC Exception Types" section later in this chapter covers how youcan determine exception-specific information from each type of MFC exception caughtin a catch block.</P><BLOCKQUOTE> <P><HR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -