throw
和catch
的方式进行传递和处理
try
:try作用域中的代码段受异常机制保护(必须和catch
关键字配对)catch
:与try关键字配对(一个try可以匹配多个catch),用于接收try作用域代码段中特定类型的异常对象,在catch
作用域中可以对异常进行处理throw
:代码段中用于抛出异常对象的关键字#include
#include
using namespace std;
//用于封装错误信息的类
class Object
{
public:
//异常对象的构造
Object(const char * str = "")
: _msg(str)
{}
private:
string _msg;
};
void function(bool judge)
{
if (judge)
{
//满足某种条件,抛出临时构造的异常对象
throw Object("程序异常");
}
}
int main()
{
try
{
//try作用域中的代码块受异常机制保护
function(true);
}
catch (Object e1)//Object表示类的类型名,e1类似于函数形参(catch机制类似于函数调用)
{
cout << "捕获Object类型的异常" << endl;
//处理异常
}
catch (...) //...可以捕获任意类型的异常
{
cout << "捕获未知异常" << endl;
//处理异常
}
return 0;
}
catch
关键字的参数和throw
抛出的对象类型必须是相匹配的,此时异常对象才能被catch
接收(catch(...)
可以接受任意类型的异常对象)(catch
机制类似于函数调用)try
和catch
关键字组时,抛出的异常会根据对象类型匹配离throw
语句位置最近的catch
语句.throw
抛出的异常必须被接收,否则程序就会直接终止throw
抛出异常后,运行的程序将直接跳转到相应的catch
作用域中,throw
语句之后的代码段便无法被执行,要尤其注意这种代码跳转机制可能引发的内存泄漏问题(比如delete
语句被跳过)异常如果抛出后没有被接收,程序就会终止,因此函数的设计者应该向调用者声明函数是否能够抛出异常以及能够抛出什么类型的异常
void func() throw(TypeA,TypeB,TypeC,TypeD);
表示函数func能够抛出TypeA,TypeB,TypeC,TypeD四种类型的异常对象void func() noexcept
表示函数不会抛出任何异常catch
的参数类型,就可以实现对所有子类异常对象的捕捉(父类和子类对象的赋值兼容),再通过多态机制就可以调用各个子类异常对象的功能接口:#include
#include
#include
using namespace std;
// 服务器开发中通常使用的异常继承体系
//基类Exception
class Exception
{
public:
Exception(const string& errmsg, int id)
:_errmsg(errmsg)
, _id(id)
{}
virtual string what() const
{
return _errmsg;
}
protected:
string _errmsg;
int _id;
};
//子类SqlException
class SqlException : public Exception
{
public:
SqlException(const string& errmsg, int id, const string& sql)
:Exception(errmsg, id)
, _sql(sql)
{}
//重写父类虚函数
virtual string what() const override
{
string str = "SqlException:";
str += _errmsg;
str += "->";
str += _sql;
return str;
}
private:
const string _sql;
};
//子类CacheException
class CacheException : public Exception
{
public:
CacheException(const string& errmsg, int id)
:Exception(errmsg, id)
{}
//重写父类虚函数
virtual string what() const override
{
string str = "CacheException:";
str += _errmsg;
return str;
}
};
//子类HttpServerException
class HttpServerException : public Exception
{
public:
HttpServerException(const string& errmsg, int id, const string& type)
:Exception(errmsg, id)
, _type(type)
{}
//重写父类虚函数
virtual string what() const override
{
string str = "HttpServerException:";
str += _type;
str += ":";
str += _errmsg;
return str;
}
private:
const string _type;
};
//功能接口
void SQLMgr()
{
srand(time(0));
if (rand() % 7 == 0)
{
throw SqlException("权限不足", 100, "select * from name = '张三'");
}
}
//功能接口
void CacheMgr()
{
srand(time(0));
if (rand() % 5 == 0)
{
throw CacheException("权限不足", 100);
}
else if (rand() % 6 == 0)
{
throw CacheException("数据不存在", 101);
}
SQLMgr();
}
//功能接口
void HttpServer()
{
srand(time(0));
if (rand() % 3 == 0)
{
throw HttpServerException("请求资源不存在", 100, "get");
}
else if (rand() % 4 == 0)
{
throw HttpServerException("权限不足", 101, "post");
}
CacheMgr();
}
int main()
{
while (1)
{
this_thread::sleep_for(chrono::seconds(1));
try
{
HttpServer();
}
catch (const Exception& e) // 这里使用父类引用实现子类对象的捕捉
{
//多态调用
cout << e.what() << endl;
}
catch (...)
{
//捕捉到未知异常
cout << "Unkown Exception" << endl;
}
}
return 0;
}