Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3976055
  • 博文数量: 408
  • 博客积分: 10227
  • 博客等级: 上将
  • 技术积分: 9820
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-17 21:48
个人简介

非淡泊无以明志,非宁静无以致远

文章存档

2022年(1)

2021年(1)

2020年(2)

2019年(5)

2018年(4)

2017年(3)

2016年(24)

2015年(8)

2014年(7)

2013年(3)

2012年(1)

2011年(23)

2010年(179)

2009年(147)

分类: C/C++

2010-12-07 17:25:22

 

1.MFC异常处理 

   MFC中异常处理的语法和语义构建在标准C++异常处理语法和语义的基础之上,其解决方案为: 

   MFC异常处理 = MFC 异常处理类  

 1.1 

   MFC定义了TRYCATCH(及AND_CATCHEND_CATCH)和THROW(及THROW_LAST)等用于异常处理的宏,其本质上也是标准C++trycatchthrow的进一步强化,由这些宏的定义可知:

#ifndef _AFX_OLD_EXCEPTIONS 

#define TRY { AFX_EXCEPTION_LINK _afxExceptionLink; try { 

#define CATCH(class, e) } catch (class* e) \ 

{ ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); \ 

_afxExceptionLink.m_pException = e; 

#define AND_CATCH(class, e) } catch (class* e) \ 

{ ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); \ 

_afxExceptionLink.m_pException = e; 

#define END_CATCH } } 

#define THROW(e) throw e 

#define THROW_LAST() (AfxThrowLastCleanup(), throw) 

// Advanced macros for smaller code 

#define CATCH_ALL(e) } catch (CException* e) \ 

{ { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \ 

_afxExceptionLink.m_pException = e; 

#define AND_CATCH_ALL(e) } catch (CException* e) \ 

{ { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \ 

_afxExceptionLink.m_pException = e; 

#define END_CATCH_ALL } } } 

#define END_TRY } catch (CException* e) \ 

{ ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \ 

_afxExceptionLink.m_pException = e; } }  

这些宏在使用语法上,有如下特点: 

   1)用TRY 块包含可能产生异常的代码; 

   2)用CATCH块检测并处理异常。要注意的是,CATCH块捕获到的不是异常对象,而是指向异常对象的指针。此外,MFC靠动态类型来辨别异常对象; 

   3)可以在一个TRY 块上捆绑多个异常处理捕获块,第一次捕获使用宏CATCH,以后的使用AND_CATCH,而END_CATCH则用来结束异常捕获队列; 

   4)在异常处理程序内部,可以用THROW_LAST 再次抛出最近一次捕获的异常。 

1.2 MFC 异常处理类 

   MFC较好地将异常封装到CException类及其派生类中,自成体系,下表给出了MFC 提供的预定义异常: 

异常类  含义  

CMemoryException  内存不足  

CFileException  文件异常   

CArchiveException  存档/序列化异常  

CNotSupportedException  响应对不支持服务的请求  

CResourceException  Windows 资源分配异常  

CDaoException  数据库异常(DAO 类)  

CDBException  数据库异常(ODBC 类)  

COleException  OLE 异常  

COleDispatchException  调度(自动化)异常  

CUserException  用消息框警告用户然后引发一般 CException 的异常  

   标准C++的异常处理可以处理任意类型的异常,而3.1节的MFC 宏则只能处理CException 的派生类型,下面我们看一个CFileException的使用例子: 

#include  

#include "afxwin.h" 

int main() 

{ 

  TRY 

  { 

   CFile f( "d:\\1.txt", CFile::modeWrite ); 

  } 

  CATCH( CFileException, e ) 

  { 

   if( e->m_cause == CFileException::fileNotFound ) 

    cout << "ERROR: File not found\n" << endl;

}

}

要想这个程序能正确地执行,我们可以在第一个__try块的外面再套一个__try块和一个接收filter-expression返回值为EXCEPTION_EXECUTE_HANDLER__except块,

程序改为: 

//4-2 

#include "stdio.h" 

void main() 

{ 

  int* p = NULL; // 定义一个空指针 

  puts("SEH begin"); 

  __try 

  { 

   __try 

   { 

    puts("in try"); 

    __try 

    { 

     puts("in try"); 

     *p = 0; // 引发一个内存访问异常 

    } 

    __finally 

    { 

     puts("in finally"); 

    } 

   } 

   __except(puts("in filter"), 0) 

   { 

    puts("in except"); 

   } 

  } 

  __except(puts("in filter"), 1) 

  { 

   puts("in except"); 

  } 

  puts("SEH end"); 

}  

   程序输出: 

SEH begin 

in try //执行__try 

in try //执行嵌入的__try 

in filter1 //执行filter-expression,返回EXCEPTION_CONTINUE_SEARCH 

in filter2 //执行filter-expression,返回EXCEPTION_EXECUTE_HANDLER 

in finally //展开嵌入的__finally 

in except2 //执行对应的__except 

SEH end //处理完毕  

   由此可以看出,因为第一个__exceptfilter-expression返回EXCEPTION_CONTINUE_SEARCH 的原因,"in except1"没有被输出。程序之所以没有崩溃,是因为最终碰到了接收EXCEPTION_EXECUTE_HANDLER的第2__except 

   SEH使用复杂的地方在于较难控制异常处理的流动方向,弄不好程序就""了。

如果把例4-1中的__except(puts("in filter"), 1)改为__except(puts("in filter"), -1),程序会进入一个死循环,输出: 

SEH begin 

in try //执行__try 

in try //执行嵌入的__try 

in filter //执行filter-expression,返回EXCEPTION_CONTINUE_EXECUTION 

in filter 

in filter 

in filter 

in filter 

//疯狂输出"in filter"  

   最后疯狂地输出"in filter",我们把断点设置在__except(puts("in filter"), -1)语句之前,按F5会不断进入此断点。 

2.各种异常处理的对比 

   下表给出了从各个方面对这本文所给出的Visual C++所支持的四种异常处理进行的对比: 

        异常处理  支持语言  是否标准  复杂度  推荐使用  

       C异常处理  C语言    标准C     简单   推荐  

       C++异常处理  C++语言  标准C++  较简单  推荐  

       MFC异常处理 C++语言  仅针对MFC程序  较简单  不推荐  

       SEH异常处理  CC++语言  仅针对Microsoft编译环境  较复杂  不推荐  

   本文所讲解的仅仅是Visual C++异常处理的初步知识,对于更深入的内容,还需要我们在不断的编程过程中去领悟和学习。 

 

阅读(12481) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~