1.C++异常处理
在MFC中应使用C++的异常处理机制,不推荐使用MFC的宏
为了使C++异常处理可用,需要进行如下设置:工程->设置->C/C++选项卡->分类C++语言->允许异常处理。或者使用/GX编译选项,默认情况下是/GX-
C++的异常处理结构为:
try{
//可能引发异常的代码
}catch(type_1 e)
{
// type_1类型异常处理
}catch(type_2 e)
{
// type_2类型异常处理
}catch (...)//会捕获所有未被捕获的异常,必须最后出现
{
}
在C++中,throw抛出异常的特点有:
(1)可以抛出基本数据类型异常,如int和char等;
(2)可以抛出复杂数据类型异常,如结构体(在C++中结构体也是类)和类;
(3)C++的异常处理必须由调用者主动检查。一旦抛出异常,而程序不捕获的话,那么abort()函数就会被调用,弹出如图1所示的对话框,程序被终止;
(4)可以在函数头后加throw([type-ID-list])给出异常规格,声明其能抛出什么类型的异常。type-ID-list是一个可选项,其中包括了一个或多个类型的名字,它们之间以逗号分隔。如果函数没有异常规格指定,则可以抛出任意类型的异常。
C++的标准异常
namespace std
{
//exception派生
class logic_error; //逻辑错误,在程序运行前可以检测出来
//logic_error派生
class domain_error; //违反了前置条件
class invalid_argument; //指出函数的一个无效参数
class length_error; //指出有一个超过类型size_t的最大可表现值长度的对象的企图
class out_of_range; //参数越界
class bad_cast; //在运行时类型识别中有一个无效的dynamic_cast表达式
class bad_typeid; //报告在表达试typeid(*p)中有一个空指针p
//exception派生
class runtime_error; //运行时错误,仅在程序运行中检测到
//runtime_error派生
class range_error; //违反后置条件
class overflow_error; //报告一个算术溢出
class bad_alloc; //存储分配错误
}
exception类的原型:
请注意观察上述类的层次结构,可以看出,标准异常都派生自一个公共的基类exception。基类包含必要的多态性函数提供异常描述,可以被重载。
class exception
{
public:
exception() throw();
exception(const exception& rhs) throw();
exception& operator=(constexception& rhs) throw();
virtual ~exception() throw();
virtual const char *what() const throw();
};
函数what():返回一个表示异常的字符串。
从exception类派生一个自己的类:
#include <iostream>
#include <exception>
using namespace std;
class myexception:public exception
{
public:
myexception():exception("一个重载exception的例子")
{}
};
int main()
{
try
{
throw myexception();
}
catch (exception &r) //捕获异常
{
cout << "捕获到异常:"<< r.what()<< endl;
}
return 0;
}
程序运行,输出:
捕获到异常:一个重载exception的例子
一般的,我们直接以基类捕获异常,例如,本例中使用了
catch (exception &r)
然后根据基类的多态性进行处理,这是因为基类中的what函数是虚函数。
2.捕获所有异常
#include <eh.h>
#include <process.h>
#include <iostream.h>
typedef struct tagPoint //定义Point结构体(类)
{
int x;
int y;
} Point;
static voidf()//扔出Point异常的函数
{
Point p;
p.x = 0;
p.y = 0;
throw p;
}
int main()
{
try
{
// throw 100; //抛出 int 型异常
// throw "a string"; //抛出字符串型异常
f(); //抛出Point异常
}
catch (int) //捕获int异常
{
cout<<"捕获到int异常"<<endl;
}
catch (char *str) //捕获Point异常
{
cout<<"捕获到字符型串异常"<<endl;
}
catch (Point e) //捕获Point异常
{
cout<<"捕获到Point自定义类型的异常"<<endl;
}
catch (...) //其它所有类型
{
cout<<"捕获到其它类型的异常"<<endl;
}
return 0;
}
3.set_terminate:
处理未设置异常处理函数的异常,个人认为可以用catch (...){}而不用它
需要头文件<eh.h>
多线程程序中,各个terminate函数是独立的,每个线程都有其terminate函数
在调试器不存在的情况下才工作
Terminate函数中不能再抛出异常
如果我们不设置terminate函数,则默认情况下调用abort函数
#include <eh.h>
#include <process.h>
#include <iostream.h>
void term_func();
void main()
{
int i = 10,j = 0, result;
set_terminate( term_func );
try
{
if( j == 0 )
throw "Divide by zero!";//抛出异常,由terminate函数捕获,
else
result = i/j;
}
catch( int )//不会由该函数捕获
{
cout << "捕获到整型异常.n";
}
cout<< "This should neverprint.n";
}
void term_func()
{
cout<< "term_func() was called byterminate().n";
// ...cleanup tasks performed here
// If thisfunction does not exit, abort is called.
exit(-1);
}