目录
1.c++异常的由来
2.怎么使用异常来解决问题
3.异常安全
4.异常规范
5.异常处理的优缺点
1.c++异常的由来
在c语言中,如果程序出现了错误,采用的是返回错误码的方式。最常见的:
int main()
{
return 0;
}
这里的return 0的0就是表示返回正确。
我们需要进行查错误码表才可以得到是什么错误,实在太麻烦。为了解决这个问题,提出了异常的概念。
2.怎么使用异常来解决问题
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
;
void Div(int a, int b)
{
if (b == 0)
throw "div false\n"; //抛出异常
cout << (double)a / double(b) << endl;
}
int main()
{
try
{
Div(2, 0);
}
catch (const char* s) //接受异常
{
cout << s << endl;
}
catch(...) //可以接收任意的错误信息,防止有错误信息漏跑。
{
cout<<"unknowed error\n"<<endl;
}
return 0;
}
这就是利用异常来进行检查除数是否为0的基本做法。在调用Div函数时,如果抛出了异常,就会由catch接收,并打印出错误信息。抛出的异常会先从当前的函数栈帧进行查找接收。然后再出栈帧再全局的范围顺序查找接收。
有时错误信息比较复杂,那我们就需要用指定的类来进行封装实现。同时,我们定义出来的各种错误信息的类都应该继承于同一个基类。这样我们捕捉错误信息的时候,就只需要用基类来捕获。
例如:
class Exception
{
protected:
int _id;
string _ermsg;
public:
Exception(int id,string ermsg)
:_id(id)
,_ermsg(ermsg)
{}
virtual string what() //获取错误信息
{
return _ermsg;
}
};
class Sqlerror :public Exception //继承实现某个特殊的错误类
{
string _sql_id;
public:
Sqlerror(int id, string sql_id, string ermsg)
:Exception(id, ermsg)
, _sql_id(sql_id)
{}
virtual string what()// 添加上sql_id
{
string str = "exception: ";
str += _sql_id;
str += "->";
str += _ermsg;
return str;
}
};
void sqltest() //测试出现错误的情况
{
srand((unsigned int) time(0)); //设置随机数源
int i = rand(); //生成随机数
if (i % 3 == 0) //%3为0的时候表示权限不足
throw(Sqlerror(i,"权限不足","select * from table where name=李四"));
else if(i % 4 == 0) //%4为0的时候表示数据不存在
throw(Sqlerror(i, "数据不存在", "select * from table where name=李四"));
}
int main()
{
while (1) //循环测试
{
Sleep(1); //休眠一秒,别搞的太快了。
try {
sqltest();
}
catch (Exception& err) //以基类的引用调用子类
{
cout << err.what() << endl;
}
catch (...) //最后一道保险,捕获未知异常
{
cout << "unkowned error\n" << endl;
}
}
return 0;
}
这样我们就可以只用一个基类引用来调用各种不同的子类,显示出不同的错误。
3.异常安全
尽量不要在构造函数或者析构函数中抛异常,这样容易导致初始化不完全或者资源释放不完全。
同时,在new和delete,在在lock和unlock之间抛出了异常也会导致问题。不过可以使用raii(智能指针)解决这个问题。
4.异常规范
直接上代码,看了就懂。
// 这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void fun() throw(A,B,C,D);
// 这里表示这个函数不会抛出异常
void* operator delete (std::size_t size, void* ptr) throw();
5.异常处理的优缺点
优点:
a.比起错误码,显示错误信息更加直观。
b.抛出异常会直接被捕捉,不像返回错误码,如果涉及多层调用,需要不断向上递归返回错误码。
c.使用第三方库需要使用异常操作
d.在无返回值的函数中,也只能采用异常处理这种操作,比如构造函数。
缺点:
a.在一个大项目中去调试程序会非常痛苦。你可能打了一个断点,程序执行到某个位置抛出了异常,直接就跳到了一个预期之外的地方。
b.c++标准库提供的异常类我们都不太喜欢使用。各个公司采用不同的异常处理方式,导致场面极度混乱,并且必须规范使用。