int Divide(int a,int b) { if(b == 0) { cout << "b is zero" << endl; std::abort(); // 这句执行会直接退出程序,而不是回到main函数 } return a / b; } int main() { cout << Divide(1, 0) << endl; cout << "main end" << endl; return 0; }
在使用Divide之前应当判断a,b值的,依靠程序员来执行检查是不安全的
根据函数的返回值,来判断是否异常
例如可以定义很多error值,返回不同就表示不同的error
异常提供了将控制权从程序的一部分传递到另一部分的途径
对异常处理有3个组成部分
throw语句类似跳转,throw关键字引发异常,并且其随后的值指出了异常的特征
处理异常用catch捕获
执行throw语句类似执行返回语句,因为它也将终止函数的执行;但是throw不是将控制权返回给调用程序,而是导致程序沿着函数调用序列后退,,直到找到包含try块的函数
如果函数引发异常,而没有try块或没有匹配的处理函数,程序最终降调用abort()函数。
int Divide(int a,int b) { if(b == 0) { throw "b is zero"; } return a / b; } void fun() { try{ cout << "fun()" << endl; }catch(const char* err){ cout << err << endl; } } void fun2() { try{ cout << "fun2()" << endl; }catch(const char* err){ puts(err); } } int main() { try{ cout << "main()" << endl; }catch(const char* err){ puts(err); } fun(); fun2(); cout << Divide(1, 0) << endl; cout << "main end" << endl; return 0; }
必须是 try{}catch(){}捕获异常
try{ Divide(1, 0); }catch(const char* err){ puts(err); }
void myStrcpy(char *to, char *from) { if (from == NULL) { throw "源buf出错"; // 这里抛出的异常是char * } if (to == NULL) { throw "目的buf出错"; } while (*from != '\0') { *to = *from; to++; from++; } *to = '\0'; return; } int main() { //异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象, //都会被自动析构。析构的顺序与构造的顺序相反。 //这一过程称为栈的解旋(unwinding) try { myStrcpy(NULL,NULL); // 接下去的语句都不执行 //myStrcpy(NULL,"source"); } catch(char* s) { puts(s); } catch(string &e) { cout << e << endl; } catch (...) { cout << "未知类型异常" << endl; } return 0; }
class MyException { public: void pf(){ cout << "error" << endl; }; }; class Test { public: Test(int a = 0, int b = 0) { this->a = a; this->b = b; cout << "Test 构造函数执行" << "a:" << a << " b: " << b << endl; } void printT() { cout << "a:" << a << " b: " << b << endl; } ~Test() { cout << "Test 析构函数执行" << "a:" << a << " b: " << b << endl; } private: int a; int b; }; void myFunc() // throw (MyException) { Test t1(1,1); // Test t2(2,2); // cout << "定义了两个栈变量,异常抛出后测试栈变量的如何被析构" << endl; throw MyException(); } int main() { //异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象, //都会被自动析构。析构的顺序与构造的顺序相反。 //这一过程称为栈的解旋(unwinding) try { myFunc(); } catch(MyException &e) //catch (MyException) { e.pf(); //这里不能访问异常对象 cout << "接收到MyException类型异常" << endl; } catch (...) { cout << "未知类型异常" << endl; } return 0; }
int Divide(int a,int b) { if(b == 0) { throw "b is zero"; } return a / b; } void fun2() { try{ Divide(1, 0); }catch(const char err){ cout << "fun2 catch exception" << endl; printf("%c\n",err); } catch(const char* err){ cout << "fun2 catch exception" << endl; puts(err); } cout << "end fun2()" << endl; } int main() { try{ fun2(); }catch(const char* err){ cout << "main catch exception" << endl; puts(err); } cout << "main end" << endl; return 0; }
上述代码中, fun2将不捕获到 (const char* err)的异常,那么fun2继续执行完成,main中将捕获不到异常
int Divide(int a,int b) { if(b == 0) { throw "b is zero"; } return a / b; } void fun2() { try{ Divide(1, 0); }catch(const char err){ cout << "fun2 catch exception" << endl; printf("%c\n",err); } cout << "end fun2()" << endl; } int main() { try{ fun2(); }catch(const char* err){ cout << "main catch exception" << endl; puts(err); } cout << "main end" << endl; return 0; }
fun2捕获不到(const char* err)的异常, fun2函数将不会正常的执行完全,会退到main函数中,main捕获到异常
例子2中 若main也不捕获(const char* err)异常,那么程序将调用abort(main函数退出之前就abort)
class Demo{ public: Demo(){ cout << "Demo::Demo()" << endl; } ~Demo(){ cout << "Demo::~Demo()" << endl; } }; int Divide(int a,int b) { Demo d1; if(b == 0) { throw "b is zero"; } return a / b; } void fun2() { Demo d2; try{ Divide(1, 0); }catch(const char err){ cout << "fun2 catch exception" << endl; printf("%c\n",err); } cout << "end fun2()" << endl; } int main() { try{ fun2(); }catch(const char* err){ cout << "main catch exception" << endl; puts(err); } cout << "main end" << endl; return 0; }
函数由于异常没能执行完,但是函数中的栈仍被释放,一直查找到最终的catch,中间的栈的自动变量都将被释放。
class Demo{ public: Demo(){ cout << "Demo::Demo()" << endl; } ~Demo(){ cout << "Demo::~Demo()" << endl; } }; int Divide(int a,int b) { Demo *d1 = new Demo(); if(b == 0) { delete d1; throw "b is zero"; } delete d1; return a / b; }