c++--------异常处理机制

为什么会有异常处理——处理错误

传统的错误处理机制:

1、直接终止程序;
2、返回错误码;
3、返回合法值,忽略错误;
4、调用一个预先设置好的出现错误时调用的函数(回调函数),像signal函数。
有些时候错误不能说一出现就杀掉程序,那么对于一些应用型程序,崩溃了会造成很大的损失,那么就可以抛异常出去,再在其他地方捕获异常,然后根据合理的方式处理掉错误。

异常处理的基本形式

1、基本用法

当一个catch无法完全处理一个异常,就可以交给更外层的catch来处理,就会重新抛异常。

class exception
{
exception(char* msg)
:_errmsg(msg);
private:
    string * _errmsg;
};
void func1(){
throw string("string");
}
void func2(){
try
{
func1();
}
catch(string& errmsg)
{
cout<<errmsg<<endl;
exception e("rethrow exception");
throw e;
}
}
void func3(){
try
{
func2();
}
catch(string& s){
cout<<"catch"<<endl;//不匹配无法捕获
}
}

2、说明

1)throw可以抛出任意类型的变量,catch按照被抛出变量的编译时类型进行匹配(类型匹配而且距离最近的)。
2)异常处理是为了保证程序不会异常退出。
3)如果抛出的异常找不到匹配的类型,程序最终会异常终止
4)程序进入try模块,其内部的局部变量会调用对象的析构函数自动释放,所以要保证析构函数不能抛异常
5)调用函数程序控制权还是会返回到函数调用处,但是抛异常控制权就永远不会回到抛出异常的地方
6)异常匹配时,只允许三种类型的转换
const—-非const ;派生类—基类;数组——指向数组类型的指针,函数—–指向函数的指针;除此之外必须完全匹配
7)异常抛出的对象由编译器管理,catch接收对象如果不是引用或者指针就会进行拷贝,但是异常对象通常是程序结束才释放

3、栈展开

如图所示就是栈的展开过程:
这里写图片描述

使用异常的建议

1、不要在构造函数中抛异常,构造函数负责对象的构造和初始化,如果抛异常会导致对象不完整或者没有完全初始化。

2、不要在析构函数中抛异常。(会导致内存泄漏或者,句柄未关闭等错误)。

3、简单错误可以不使用异常

4、异常会导致执行流乱跳,不可以用来代替switch和if-else语句。

5、不可恢复的错误不要使用异常。

异常的优缺点

优点

1、清楚的知道错误原因,而且不至于导致程序崩溃的坏结果。
2、应用多种语言c++/python/java,使得语言兼容性强。
3、测试框架中使用异常方便。

缺点

1、导致执行流乱跳,不方便跟踪调试。
2、会有异常安全问题,此时应该结合RAII编写异常安全的代码。(智能指针)
3、异常加上使得代码量大,增加编译时长,不过现代cpu挺快,就没有多大影响。

猜你喜欢

转载自blog.csdn.net/cx2479750196/article/details/80781912