深入了解C++异常处理
基本的异常处理异常处理机制暂缓问题处理不在当前函数中处理在他的调用者中处理先上车后补票什么是异常任何东西都可以认为是异常错误只是异常的一种异常一旦被抛出不做处理如果引发异常会调用默认abort函数终止程序捕获和处理异常throw 抛出异常 (值是任何类型都可以只是我们处理异常的一个参照类似返回值)try(检查捕获)和catch(处理异常) 必须是一起出现并且它们的括号{ }不能省略tip: 任何东西都可以认为是异常错误只是异常中的一种---出现一种情况不能让程序正常运行怎么抛出异常12345678910111213141516//求a和b的余数 怎么抛出异常intdivision(inta,intb){if(b0)throw0;//抛出一个值任意---之后处理returna/b;}voidprint(inta,intb){coutdivision(a,b);}intmain(){print(1,0);}/* 把b0 的情况称为异常,b0 时代码不成立,会调用默认abort函数终止程序 */异常一旦被抛出不做处理如果引发异常会调用默认abort函数终止程序捕获和处理异常12345678910111213141516171819202122232425262728//try 与catch必须是一起出现并且他们的括号{}不能省略try{//正常需要检查是否存在异常的代码}catch(类型)//理解为switch中case语句{//处理是根据抛出数据类型决定如何处理 匹配项 匹配抛出异常的类型}//一个try可以对应多个catchtry{//...}catch(int){}catch(double){}catch(string){}//catch和if else_if 执行机制是一样的只能执行一个匹配项小知识对try{ } catch(){ } 的理解:在当前位置引发异常直接从这个位置跳到catch的位置执行catch的代码 --- 类似switch case 语句catch中int和char不会做转换写两个相同的类型不被允许哪段代码先引发异常就先调用catch123456789101112131415161718192021intdivision(inta,intb){if(b0)throw0;returna/b;}voidprint(inta,intb){coutdivision(a,b);}intmain(){try{print(1,0);//检查异常cout别的代码endl;//这一句不会运行,会直接跳到catch}catch(int)//抛出的是int类型,捕获int类型{cout除数不能为0endl;}}程序能抛出(存在)多个异常但是只能同时处理1个异常不能同时引发多个异常不存在异常的描述 --- 标识性作用throw ()noexcept12345678910//某个函数不存在异常,在某个函数后面用throw() 描述,表示它不存在异常voidprint()throw(){cout 当前函数不存在抛出异常操作 endl;}voidprintData() noexcept{cout c新标准中的关键字: 不存在抛出异常操作 endl;//throw 0; 一旦说明没有异常操作就不能抛出}删减符 ...任何类型的异常都捕获 不管抛出啥在哪里抛出的只要引发异常都可以捕获到12345catch(...){cout 捕获任何类型的异常 endl;}异常处理中的传参操作 --- 可以写一个变量进去catch(int a)/* 隐藏了一个传参操作 可以传任何类型包括自定义类型都可以 */注意c中string的处理 /* string类型与const char* 类型区别 */代码解析对 通过抛出字符串隐藏了一个传参操作 的理解123456789101112131415161718intdivisor(inta,intb){if(b 0)throwstring(除数不能为0);returna / b;}intmain(){try{divisor(1, 0);}catch(string str)//把throw的内容赋值给str str除数不能为0{cout str endl;}}注意string类型与const char* 类型区别 --- 出现类型不匹配c对传参类型要求更严格1234567891011121314151617181920212223242526272829303132intdivisor(inta,intb){if(b 0)throw除数不能为0;//抛出异常 解析为char* 类型 写catch时不能直接当作stringif(b1)throw除数不能为1;/* 不同问题的抛出,不能用固定类型(int、char...), 可以选择抛出不同字符串处理 string1,string2,string3... 通过传参的方式去描述问题 */if(b2)throwstring(除数不能为2);//需构造无名参数作捕获对象处理---需要自己触发returna / b;}intmain(){try{divisor(1, 0);//直接触发异常}catch(constchar* str)//抛出的是char* 类型,不能当作string{cout str endl;}try{divisor(1, 2);}catch(string str)//如果要捕获string类型,需要自己构造一个string对象返回{cout str endl;//直接输出str}}可以抛出自己类的对象1234567891011121314151617181920212223242526272829303132333435363738394041classError{public:Error(constchar* str 未知错误) :str(str) {}constchar* what()const{returnstr.c_str();}protected:string str;};voidinsertArray(intarray[],int* curNum,intposData,intmaxLength){if(*curNum maxLength)//33{throwError(数组下标溢出);}//0 1 2array[*curNum] posData;//array[3]3(*curNum);}intmain(){try{intarray[3] { 0,0,0 };intcurNum 0;for(inti 0; i 4; i){insertArray(array, curNum, i, 3);}}catch(Error str){cout str.what() endl;}return0;}标准库当中的异常类1#includeexception //父类(基类)子类很多子类描述的问题不同而已例子 const char* _ptr 一个数据成员用于描述标准库当中异常的字符串用字符指针存放那个字符串what( )方法 用于返回数据成员的 1.虚函数 2.不存在异常return _ptr ? _ptr : unknow判断char* 类型的指针是不是为空不等于空返回你描述的错误等于空由于没有传参返回未知错误unknow引发标准库中内存申请失败的异常发现代码出现abort( )错误可以通过这种方式找到这里是针对内存申请失败做了单一处理如果不做处理会直接调用abort函数终止程序1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253#include exception#include iostreamusingnamespacestd;classException{public:Exception(constchar* ptrUNKNOW) :ptr(const_castchar*(ptr)){}/*构造函数 干掉常属性*/virtualconstchar* what()const//父类是虚函数 且不存在异常{returnptr;}protected:char* ptr;};//子类继承父类classBad_alloc :publicException{public:Bad_alloc(constchar* _Message bad exception) :Exception(_Message) {}/*调用父类的构造函数抛出bad exception*/protected:};//子类继承父类 调用父类构造函数classRun_time :publicException{public:Run_time(constchar* _Message run_time error) :Exception(_Message) {}protected:};intmain(){try{while(1){int* p newint[1024*1024*10];//一直做内存申请,不做释放,最后一定会内存申请失败}}catch(bad_alloc object)/* 内存申请失败,调用bad_alloc 标准库中的异常,创建一个对象接收一下,子类中的what()方法调用父类中的what()方法打印 */{cout object.what() endl;}return0;}/*输出*/bad allocation//调用时抛出 bad allocation 是子类对象调用继承下来的what()方法//一般写代码出现莫名的中断,原因是不做异常处理,引发了abort函数中断程序,一般这种错误都是特殊错误标准库中传两个参数起到标识作用由于引发了不同的错误不同错误对应了不同的错误编码 对这些错误有特定的描述 --- 工具 --- 错误查找 --- 输入错误编码值3错误信息系统找不到指定的路径