什么是异常?异常时面向对象语法处理错误的一种方式(大多数面向对象的语言都有)。
c语言传统处理错误的方式有哪些呢?(1)返回错误码,有些API接口都是把错误码放到全局变量errno中。(2)终止程序,比如发生越界等严重问题时,我们也可以主动调用exit()。
传统处理错误方法的缺陷有哪些?(1)如果如果函数有返回值,在发生错误时,就有可能发生返回值与错误码相等的情况,很难处理。(2)如果调用的函数栈很深,发生错误时,很难确定错误发生在哪一层,处理比较难受。
使用异常可以有效解决这个问题。下面是处理除零错误时的异常使用,执行结果如下。如果不使用异常,而是选择返回一个值来标定错误的话,不好确定返回值,因为返回的值有可能就是除法的计算结果。此时只能如果不想终止程序的话只能使用异常。异常的使用方法是,在可能发生错误的地方抛出异常,可能抛出异常的代码段要使用try与括号包裹运行,后续要使用catch以及{}捕捉异常,只要可能有异常抛出就一定要捕捉。使用异常的好处是在捕捉后可以自己写代码来表征异常。
int divide(int l, int r)
{
if (r == 0)
{
throw (string)"cuowu";
}
return l / r;
}
int main()
{
try
{
divide(1, 0);
}
catch (string a)
{
cout << a << endl;
}
}
throw可以抛出任何类型的对象,可以是自定义类型和内置类型,catch时也得设置对应的捕捉代码块。异常发生时,程序会直接跳转到对应的catch内。发生异常时,调用的catch采取的是就近原则,如果是多层栈帧,会优先在内层的栈帧中寻找catch,如果没有就跳出到下一层寻找。可以使用下面这种写法来捕获没有匹配到的任意类型的异常。
catch(...)
{
//
}
由于抛出异常的地方是会直接跳转到外层的catch的,可能会出现动态开辟的空见还没析构就跳出的情况,造成内存泄漏。就像下面这样。如果func1内发生除零错误,那么异常直接匹配到main()中的catch,p未析构就造成内存泄漏。处理方法是下面这样。在内部先catch以将p析构掉在直接抛出。
int divide(int l, int r)
{
if (r == 0)
{
throw (string)"cuowu";
}
return l / r;
}
void func1(int l, int r)
{
int* p = new int;
divide(l, r);
delete p;
}
int main()
{
try
{
func1(1, 0);
}
catch (string a)
{
cout << a << endl;
}
}
void func1(int l, int r)
{
int* p = new int;
try
{
divide(l, r);
}
catch(...)
{
delete p;
throw;
}
delete p;
}