}
};
voidFunc(inti)
{
if(i%3==0)
throwCErrorOverflow();
if(i%4==0)
throwCErrorNullPointer();
if(i%5==0)
throwCErrorZeroDevide();
}
intmain(intargc,char*argv[])
{
inti;
cin>>i;
try
{
Func(i);
}
catch(CErrorBase&e)
{
e.PrintError();
}
return0;
}
这样使得对异常的处理变得简单而统一,事实上,MFC的异常处理就是以此为基础的。
2.3.异常接口说明
一个函数往往要抛出异常对象,函数的使用者应当了解函数所抛出的异常,从而设置catch语句捕获异常对象,并对捕获的异常对象进行处理,但是,除非看到函数的源代码,否则函数的使用者无法从函数的原型声明中知道函数可能抛出的异常。
C++为此提供了异常的接口说明,它在函数说明中就列出了函数可能抛出的异常,因为不必了解函数代码就可以知道函数与哪些异常有关。
异常接口说明是函数声明的一部分,它紧跟在普通的函数声明之后。
异常接口说明的一般形式为:
返回类型函数名(参数列表)throw(异常类型1,异常类型2,,,);
throw后扩后内的内容是此函数可能抛出的所有异常的集合。
各类型间用逗号隔开。
例如:
voidfunc(inti)throw(char,int);
说明函数func只可能抛出char类型和int类新的异常对象,而不会再抛出其他异常。
如果一个函数声明中没有异常说明列表,那么隐含地表示函数可以抛出任何类型的异常。
例如:
intFunc(inti);
表示Func函数可能会抛出各种类型的异常。
如果规定函数不会抛出任何异常,则应该设置函数声明的异常接口为空,例如:
intFunc(inti)throw();
说明Func函数不会抛出任何异常。
3.MFC异常处理
MFC异常的语法和语义是构建在标准C++异常的语法和语义的基础上的,是用宏的方式对标准C++的异常进行包装。
MFC异常类体系是以虚函数方式组织的。
CException是所有MFC异常类的基类,
所有名字为CXXXException形式的类都是从抽象类CException派生的。
下表显示由MFC提供的预定义异常。
异常类
含义
CMemoryException
内存不足
CFileException
文件异常
CArchiveException
存档/序列化异常
CNotSupportedException
响应对不支持服务的请求
CResourceExceptionWindows
资源分配异常
CDaoException
数据库异常(DAO类)
CDBException
数据库异常(ODBC类)
COleException
OLE异常
COleDispatchException
调度(自动化)异常
CUserException
用消息框警告用户然后引发一般CException的异常
MFC则定义了一组宏:
TRY
CATCH,AND_CATCH,和END_CATCH
THROW和THROW_LAST
这些宏非常象C++的异常关键字try、catch和throw。
对于每个MFC异常类CXXXException,都有一个全局的辅助函数AfxThrowXXXException(),它构造、初始化和抛出这个类的对象。
你可以用这些辅助函数处理预定义的异常类型,用THROW处理自定义的对象(当然,它们必须是从CException派生的)。
基本的设计原则是:
用TRY块包含可能产生异常的代码。
用CATCH检测并处理异常。
异常处理函数并不是真的捕获对象,它们其实是捕获了指向异常对象的指针。
MFC靠动态类型来辨别异常对象。
可以在一个TRY块上捆绑多个异常处理函数,每个捕获一个C++静态类型的不同的对象。
第一个处理函数使用宏CATCH,以后的使用AND_CATCH,用END_CATCH结束处理函数队列。
MFC自己可能触发异常,你也可以显式触发异常(通过THROW或MFC辅助函数)。
在异常处理函数内部,可以用THROW_LAST再次抛出最近一次捕获的异常。
例,使用MFC内设异常类:
voidFunc2()
{
TRY
{
printf("raisingmemoryexception\n");
AfxThrowMemoryException();
printf("thislineshouldneverappear\n");
}
CATCH(CException,pe)//!
!
!
注意,抛出的是对象的指针
{
printf("caughtgenericexception;rethrowing\n");
THROW_LAST();//重新抛出必须用THROW_LAST();而不是THROW()
printf("thislineshouldneverappear\n");
}
END_CATCH
printf("thislineshouldneverappear\n");
}
voidFunc3()
{
TRY
{
Func2();
printf("thislineshouldneverappear\n");
}
CATCH(CFileException,pe)
{
printf("caughtfileexception\n");
}
AND_CATCH(CMemoryException,pe)
{
printf("caughtmemoryexception\n");
}
AND_CATCH(CException,pe)//捕获剩下的MFC异常类对象
{
printf("caughtgenericexception\n");
pe->ReportError();
}
END_CATCH
}
int_tmain(intargc,TCHAR*argv[],TCHAR*envp[])
{
AfxWinInit(:
:
GetModuleHandle(NULL),NULL,:
:
GetCommandLine(),0);
Func3();
}
例:
使用自定义的MFC异常派生类:
classCMyException:
publicCException
{
public:
virtualBOOLGetErrorMessage(LPTSTRlpszError,UINTnMaxError,PUINTpnHelpContext)
{
ASSERT(lpszError!
=NULL&&AfxIsValidString(lpszError,nMaxError));
charszError[]="我的错误处理信息!
";
strncpy(lpszError,szError,nMaxError-1);
lpszError[nMaxError-1]=0;
returnTRUE;
}
};
voidFunc()
{
THROW(newCMyException);
}
int_tmain(intargc,TCHAR*argv[],TCHAR*envp[])
{
AfxWinInit(:
:
GetModuleHandle(NULL),NULL,:
:
GetCommandLine(),0);
TRY
{
Func();
}
CATCH(CException,pe)
{
pe->ReportError();
}
END_CATCH
return0;
}
4.Win32结构化异常处理(SEH)
Windows95、Windows98和Windows2000(即以前的WindowsNT)支持一种称为结构化异常处理的可靠的异常处理方法,此方法涉及与操作系统的协作,并且在编程语言中具有直接支持。
“SEH异常”是意外的或是使进程不能正常进行的事件。
硬件和软件都可以检测出异常。
硬件异常包括被零除和数值类型溢出等。
软件异常包括通过调用RaiseException函数检测到并发出信号通知系统的情况,以及由Windows检测到的特殊情况。
可以使用结构化异常处理编写更可靠的代码。
可以确保资源(如内存块和文件)在发生意外终止事件时正常关闭。
还可以利用简洁的、不依靠goto语句或详细测试返回代码的结构化代码来处理具体问题(如内存不足)。
注意:
结构化异常处理文章描述C编程语言的结构化异常处理。
虽然结构化异常处理也可用于C++,但对于C++程序应使用C++异常处理。
SEH是系统一级的异常处理,当建立标准C++异常处理时,编译器最终将它翻译成SEH异常处理。
SEH实际包含两个主要功能,结束处理和异常处理。
分别通过__try{}__finally{}结构和__try{}__except(){}结构实现。
4.1.__try{}__finally{}结构
此结构能够确保__try{}块内的代码执行完毕后,进入__finally{}块中执行一些清理工作。
例:
intFunc()
{
FILE*f=NULL;
__try{
f=fopen("abc.txt","wb");
//执行一些文件处理工作
if(fwrite("aaa",1,3