异常处理
事先分析程序运行时可能出现的各种意外情况,并且分别制定相应的处理方法
异常处理的方法
- C++异常机制组成:try(检查),throw(抛出),catch(捕捉)
void Test()
{
throw 1;
}
void Test1()
{
try
{
Test();
}
catch(int)
{
cout<<"捕获"<<endl;
}
catch(...)
{
cout<<"未知异常"<<endl;
}
}
- 被检测部分必须放在try块中,否则不起作用
- try块和catch块是一个整体,catch块必须紧跟在try块之后
- 一个try-catch结构中只有一个try块,但可有多个catch块
- catch后面的圆括号中,一般只写异常信息的类型;catch(int)
- 不知道异常信息的类型,用catch(…)接收
try-catch结构和throw可以在同一函数中,也可以不
void Test() {//在同一函数 try { int* p = new int(0); throw '1'; delete p; } catch (char) { cout << "" << endl; } catch (...) { cout << "未知异常" << endl; } }
栈展开
void test1() { throw 1;//抛出 } void test2() { test1(); } void test3() { test2(); } void fun1() { try { test3(); } catch (int) { cout << "捕获"<< endl; } catch(...) { cout<<"未知异常"<<endl; } }
- 异常对象的类型必须与catch说明符的类型匹配
特殊情况:
允许从非const的对象到const对象的转换
void Test() { int a = 1; throw a; } void fun2() { try { Test(); } catch (const int err) { cout << "const int err:" << err << endl; } }
允许从派生类到基类的转换
class Base { public: Base() { cout << "Base()" << endl; } }; class Derived :public Base //class默认为私有继承 { public: Derived() { cout << "Derived()" << endl; } }; void Test1() { //throw Base();//如果是catch(Derived)不可以 //Derived d; //throw d; throw Derived(); } void fun3() { try { Test1(); } catch (Base) { cout << "基类" << endl; } }
将数据转换为指向数据类型的指针
void Array() { int arr[5] = {1,2,3,4,5}; throw arr; } void fun4() { try { Array(); } catch (int* p) { cout << *p<<endl; } }
将函数转换为指向函数类型的指针
void Funtest() { cout << "Funtest()" << endl; throw Funtest;//注意Funtest(); } void fun5() { try { Funtest(); } catch (void(*)()) //注意函数的返回值类型 { cout << "haha" << endl; } }
异常的重新抛出
void Test() { throw 1;//第一次抛出 } void Test1() { try { Test(); } catch (int&) { throw;//重新抛出 } void Test2() { try { Test1(); } catch (...) { cout << "未知异常" << endl; } }
在函数声明中进行异常情况的指定
void Test()throw()//不抛出任何异常 void Test()throw(int,double)//抛出int或double型异常
异常与构造函数和析构函数
保证不再构造函数中抛出异常,否则可能导致对象不完整或未完全初始化
保证不再析构函数中抛出异常,否则会导致内存泄漏//这种情况也导致内存泄漏 void Test() { try { int* p = new int(0); throw '1'; delete p; } catch (char) { cout << "" << endl; } catch (...) { cout << "未知异常" << endl; } }
在throw语句抛出异常信息被catch捕获时,对有关的局部对象进行析构(析构的顺序与构造的顺序相反)
class Base { public: Base() { cout << "Base()" << endl; } ~Base() { cout << "~Base()" << endl; } }; void Test() { throw Base(); } void Test1() { try { Test(); } catch (Base) { cout << "hello" << endl; } catch (...) { cout << "hello" << endl; } }
运行结果:
抛出异常后释放局部对象,被抛出的大小也还给了系统
void test() { char a = '1'; throw a; //throw 表达式会初始化一个抛出特殊的异常对象副本 } void fun() { try { test(); } catch (char) { cout << "捕获"<< endl; } catch (...) { cout << "未知异常"<< endl; } }
派生类的虚函数的异常规范必须与基类的虚函数的异常规范一样或更严格
class Base { ... virtual void fun()throw(int,double,float); } class Derived : public Base { ... virtual void fun()throw(int,double,float);//一样 virtual void fun()throw(int,double);//更严格 virtual void fun()throw(int,double,long);//错误 }
如果throw抛出的异常找不到与之匹配的catch块,那么系统就会调用一个系统函数terminate,使程序终止运行