如果你写的方法是给他人使用,那么,如果这个方法失败,最好是以抛异常的方式告诉别人,而不是在方法声明的地方写注释:“0:成功,1:网络连接失败,3:参数错误”。
抛出异常
throw 1; //抛出 int 类型异常
throw 1.2; //抛出 double 类型异常
throw "err"; //抛出 const char* 类型异常
throw exception(); //抛出 exception 类型异常
处理异常
try {
//可能抛出异常的代码块
}
catch (type e1){ //捕获类型为type的异常
//处理异常代码块
}
catch (...){ //捕获所有类型的异常
//处理异常代码块
}
异常规格说明
异常规格说明的目的是为了让使用者知道函数可能会抛出哪些异常。但也仅仅是说明而已,不会限定函数只能抛出int类型的异常。
在函数后加throw
1、在函数的声明后加上 throw(type1, type2, …),表示这个函数可能抛出type1、type2等类型的异常。
2、在函数的声明后加上 throw(),表示这个函数不会抛任何异常。
3、在函数的声明后不加 throw,表示这个函数可能抛出任何类型的异常。
再次强调,异常规格说明仅仅是说明而已!即使给一个函数后加上throw(),如果这个函数抛出异常,也可以捕捉到!
解析exception类
C++ 提供了一系列标准的异常类,如std::logic_error、std::runtime_error等。但这些标准异常类都继承了exception。
下面详细了解exception这个类。
class exception{
public:
//无参构造函数,不需关注。
exception() throw() {...}
//有参构造函数,重要。这个传入的字符串就是对这个异常的说明。
explicit exception(char const* const _Message) throw()
: _Data()
{
__std_exception_data _InitData = { _Message, true };
__std_exception_copy(&_InitData, &_Data);
}
//有参构造函数,重要。这个传入的字符串就是对这个异常的说明。int型参数貌似没用!
exception(char const* const _Message, int) throw()
: _Data()
{
_Data._What = _Message;
}
//拷贝构造函数,不需关注。
exception(exception const& _Other) throw() {...}
//赋值构造函数,不需关注。
exception& operator=(exception const& _Other) throw() {...}
//析构函数,不需关注。
virtual ~exception() throw() {...}
//返回异常说明,重要。
virtual char const* what() const
{
return _Data._What ? _Data._What : "Unknown exception";
}
private:
//结构体对象,结构体有两个成员 char const* _What(异常说明); bool _DoFree(这个有什么用?);
__std_exception_data _Data;
};
使用exception
预想是通过函数,连续抛两个异常。结果,只有第一个异常成功抛出。
代码
#include <exception>
#include <iostream>
using namespace std;
void throwException() throw(){
cout << "cout e1" << endl;
throw exception("my exception1");
cout << "cout e2" << endl;
throw exception("my exception2", 1);
}
int main()
{
try {
throwException();
}
catch (exception& e) {
cout << "catch exception " << e.what() << endl;
}
catch (...) {
cout << "catch other" << endl;
}
getchar();
return 0;
}
输出
cout e1
catch exception my exception1