c++的异常处理

时间:2021-09-11 20:41:50

c++的异常处理

1.异常处理的逻辑与顺序

异常处理对于代码来说,有点类似于goto

  • 异常处理的规律如下
    • 抛出异常后会直接跳转到异常处理块
    • throw可以在try语句块内任何地方,try后面必须紧跟catch
    • 若当前函数找不到可匹配的异常处理块,则异常会顺着函数的调用一层一层往外找,直到被处理为止,否则进程退出
    • 异常寻找异常处理块,是严格匹配类型的
    • 异常处理块类型相同时,是有优先级的,是从抛出异常开始往后找,最近的那个优先级高
    • 异常处理结束后,会接着执行异常处理块后面的代码
void MyFunc(void)
{
try
{
throw 1;//抛出异常,异常值为1,类型为int
cout << "1" << endl;//这句被跳过,不会执行
}
catch(int i)//严格匹配类型,异常值类型是int,并且该异常处理块离异常最近
{
cout << "int" << endl;//这句话被真正执行
}
catch(char i)//类型不匹配
{
cout << "char" << endl;//不执行
}
cout << "2" << endl;//这句话会被执行
}

int main(int argc, char *argv[])
{
try
{
MyFunc();
}
catch(int i)//由于优先级太低,未被执行
{
cout << "in main" << endl;
}
cout << "3" << endl;//这句话会被执行
return 0;
}

2.异常的重新解释

catch自己也能抛出异常,即将捕获的异常再次抛出。通过这个操作,可以实现异常的强制类型转换,这称之为异常的“重新解释”

try
{
func(i);//假设是某个第三方库中的函数,其抛出的异常值十分晦涩,我们可以对其“重新解释”
}
catch(int i)//将异常“重新解释”为字符串后再次抛出
{
switch(i)
{
case -1:
throw "Invalid Parameter";
break;
case -2:
throw "Runtime Exception";
break;
case -3:
throw "Timeout Exception";
break;
}
}
catch(const char* cs)//正式进行异常处理
{
cout << "Exception Info: " << cs << endl;
}

3.实际工程中的异常类

stl库中,提供了的异常类族

  • stl库中的异常类,都继承自父类exception。异常类有很多,分得很细,主要分为两个分支
    • logic_error:可避免的、明确的错误
    • runtime_error:无法避免,不可预知的错误
  • 有一点要注意,由于子类是父类的超集,子类异常可以被父类异常catch所捕获。所以在同时应用父子关系的异常类时,必须将子类异常catch放在前面,而父类异常catch放在后面。比如out_of_range是logic_error的子类,则必须如下使用:

try
{
if(...)
throw out_of_range("abcd");
else
throw logic_error("efgh");
}

catch(out_of_range e)
{
cout << "Exception1" << endl;
}
catch(logic_error e)
{
cout << "Exception2" << endl;
}