这是学习基于Linux C++做的笔记!
1、异常的定义
程序中可以检测的运行的不正常的情况
异常处理基本流程
某段程序执行期间,引发异常
另一段代码捕获异常
调用Stack::Pop()时,栈为空
解决方案:
- 定义异常类;
- 修改成员函数,出现异常时引发异常,并抛出;
- 在需要处理的地方处理该异常。
class EStackEmpty{};
class EStackFull{};
//自定义异常类JuStack声明略
int JuStack::Pop(){
if(IsEmpty())//引发空栈异常,构造该异常类的一个对象并抛出
throw EStackEmpty();
--top;--cnt;
return _stk[top];
}
void JuStack::Push(){
if(IsFull())
throw EStackFull();
_stk[top]=value;
_top++;_cnt++;
}
const int err_stack_full=1;
int main(){
JuStack stack{17};
try{//将可能出现异常的代码封装在try中
for(int i=0;i<32;i++){
stack.Push(i);
}
}
catch(const EStackFull &){//负责可能出现错误类型的异常
cerr<<"Error:Stack full"<<endl;
return err_stack_full=1;
}
return 0;
}
精心设计异常类,提供必要的异常信息
class EStackFull{
public:
EStackFull(int i):_value(i){ }
int GetValue(){return _value;}
private:
int _value;
};
void JuStack::Push(int value){
if(IsFull())
throw EStackFull(value); //使用value构造异常类输出并抛出
_stk[top]=value;
_top++;_cnt++;
}
const int err_stack_full=1;
int main(){
JuStack stack{17};
try{
for(int i=0;i<32;i++){
stack.Push(i);
}
}
catch(const EStackFull &e){//使用异常类获取异常的详细信息
cerr<<"Stack full when trying to push:"<<e.GetValue()<<endl;
return err_stack_full=1;
}
return 0;
}
异常类可以派生和继承,形成类库架构
可捕获的异常类:
- 普通型式(包括int、类):异常对象需要拷贝;
- 对某型式对象的引用:无拷贝;
- 指向某型式对象的指针:要求对象动态构造或者在catch子句中可访问;
catch子句
- 可以有多个catch子句,每个负责捕获一种、一类或全部异常;
- 捕获一种:catch(int)、catch(const char*);
- 捕获一类(该类或派生类异常):catch(const EStackFull&);
- 捕获所有:catch(…);
- catch子句按顺序执行,派生类必须在基类之前。
异常再引发
主要用于在程序终止前写入日志和实施特殊清除任务
try{
}
catch(...){//先捕获所有异常,写入日志记录异常
//...写入日志等工作
throw;//抛出原来的异常,让更顶层的catch语句进行处理
}
异常处理策略
- 引发异常和处理异常代码可能属于不同函数;
- 找到对应catch子句,处理异常;没找到继续向更顶级catch展开;
- 处理异常完毕后,程序保持catch子句所在栈框架,不会反回之前引发异常函数栈框架;
- 函数栈框架消失时,动态申请空间未执行delete,在异常抛出后无法析构