20170226C++项目班05_C/C++错误异常处理
来源:互联网 发布:淘宝加盟诈骗案进展 编辑:程序博客网 时间:2024/05/29 13:39
Calc作业(修改bug):
1:调试能力是工作必备能力之一。
2:调试应该先找到错误的源头,然后根据编程时候的逻辑线单步执行,然后在没有按照预期执行的代码段找原因。
注意:不能导出下断点,最后自己的逻辑就错乱了,很难找到bug所在
C语言错误处理方式:
1:我们之前用的最多的是通过返回值来判断是否执行成功,返回值往往是bool类型。但是不能判断出出错在哪个地方。
2:在文件操作的时候,在很多过程的时候都是可能出错的。
openFile:文件不存在
writeFile:无法写入
closeFile:无法关闭
我们可以写一个enum{ERROR_OPEN……},返回回来就可以表明错误类型,称为errorcode。
3:在方法内的错误处理,现在一般用dowhile。
4:使用jmp来实现:
#include <stdio.h>#include <setjmp.h>jmp_buf env;double Div(double d1, double d2){if (d2 == 0.0)longjmp(env, 1);//会直接跳到setjmp的地方,然后将跳到ret=1的里面去执行。return d1 / d2;}int main(){int ret;ret = setjmp(env);//当执行到longjmp的时候就会跳到这里来。重新个给ret赋值。if (ret == 0)//setjmp的时候,env默认就是为0,所以一般把正常要执行的代码放到=0的里面。{Div(5.0, 0.0);}else if (ret == 1)//在这里面也可以使用longjmp,跳出去。{printf("Div_Error");}return 0;}
5:longjmp并不是一个返回,他是一个跳转。相当于goto。他什么都不管,直接就跳转了。这种处理方式和C++里面的try chtch是一模一样的。
C++异常处理:
1:两种错误:
1:编译错误/语法错误:人为的,编译器会提示错误原因
2:运行时错误/语义错误:有很多种情况:
打开文件失败、被除数为0、内存不够……
2:异常体系:
runtime_error:
logic_error:
使用异常体系:第一步:throw,第二步:try,第三步:catch。
#include <iostream>#include <cfloat>enum EMyException{E_DIVERROR,E_FOOERROR};double Div(double d1, double d2){if (d2<DBL_EPSILON && d2>-DBL_EPSILON)throw E_DIVERROR;}void Foo(){throw E_FOOERROR;}int main(){try{Div(5.0, 0.0);Foo();}catch (EMyException e){if (e == 0)//这里会有隐式转换,如果出错会打印值printf("DivError");else if (e == E_FOOERROR)printf("FooError");}return 0;}
注意:这种try catch比C语言的逻辑更加简单,当遇到throw的时候,抛出异常,他会向前寻找有try和catch的地方,并在里面做相应的处理。
3:C++的异常可以抛出各种各样的类型:字符串指针、int、类成员类型……当catch里面没有对应的时候他会适当的转换,不能转换的时候,他还是会抛给编译器来处理,一般就会直接报错,程序终止。下面抛出自己写的异常类:
#include <iostream>#include <string>#include <cfloat>enum EMyException{E_DIVERROR,E_FOOERROR};class MyExcept{public:MyExcept(const std::string &str);void What() const;private:std::string str_;};MyExcept::MyExcept(const std::string &str):str_(str){if (str_.empty())throw "str_不能为空";//throw可以在任何一个地方出现(析构函数除外)。}void MyExcept::What() const{std::cout << str_ << std::endl;}double Div(double d1, double d2){if (d2<DBL_EPSILON && d2>-DBL_EPSILON)throw E_DIVERROR;return d1 / d2;}void Foo(){throw E_FOOERROR;}int main(){std::string ErrorCode = "Object_Error";try{Div(5.0, 0.5);throw MyExcept(ErrorCode);Foo();}catch (EMyException e){if (e == 0)//这里会有隐式转换,如果出错会打印值printf("DivError");else if (e == E_FOOERROR)printf("FooError");}catch (MyExcept e){e.What();}catch (...){printf("捕获所有异常");}return 0;}
4:异常可以在任何地方出现,包括构造函数,但是不可以在析构函数里面,而且,C++异常是安全的,他是栈安全的,当throw的时候,他会逆向按原来的顺序反回去清理栈空间,但是不会清理堆空间。throw的时候,他会按照栈来返回,返回到catch到这个的地方,如果没有任何一个地方catch,就会交给编译器,就出现我们常见的异常。我们在销毁栈的时候就是在销毁局部变量,如果是类对象的话,他还会调用析构函数。
#include <iostream>#include <string>#include <cfloat>class Text{public:Text(int id) :id_(id) { std::cout << "Text"<< id_ << std::endl; }~Text(){ std::cout << "~Text" << id_ << std::endl; }Text(const Text& text) :id_(text.id_){std::cout << "Text(Text(Text&text))" << id_ << std::endl; }private:int id_;};class MyExcept{public:MyExcept(const std::string &str);void What() const;private:std::string str_;};Text& Foo4(){Text *text = new Text(4);return *text;}Text Foo3(){Text text(3);Text t1 = Foo4();throw MyExcept("Foo3");}void Foo2(Text text){Foo3();}void Foo1(Text &text){Foo2(text);}MyExcept::MyExcept(const std::string &str) :str_(str){if (str_.empty())throw "str_不能为空";//throw可以在任何一个地方出现(析构函数除外)。}void MyExcept::What() const{std::cout << str_ << std::endl;}int main(){try{Foo1(Text(1));}catch (MyExcept e){e.What();}return 0;}
new出来的在堆上,没有释放。
注意:要保证对上的数据也安全,只能在throw的前面把堆上面的空间清理掉。
5:异常类也是可以继承的,可以分为不同种的异常类。
1:在catch的时候派生类必须写在基类之前,否则他会认为这种异常就是基类的。后面的catch派生类就没有作用。
2:非迫不得已,永远不要抛出指针。指针可能是指向栈的,而整个异常体系是清理栈的,可能导致问题。热和一个指针都可以被void*捕获。还可以那引用来接收,这样就不会产生copy。
6:C++已经包含的异常:
1:所有异常的基类:std::exception://What();,下面的属于exception的直接的派生类。
std::runtime_error:运行时出错
std::overflow_error:
std::range_error:
std::underflow_error:
std::logic_error:逻辑错误:
std::invalid_error:
std::length_error:
std::out_of_range:
std::domain_error:
std::bad_alloc:分配的时候出现错误。
std::bad_cast:类型转换错误。
7:catch操作注意事项
1:因该先捕获自己写的异常,然后捕获其他异常,最后用...捕获其他的所有异常。
2:可能在其他人写的代码里面看见一个函数后面更了一个except(),代表宰割函数会抛出异常,仅给程序员看,不建议写。
3:不要再析构函数里面抛出异常,可能出现一个异常未处理完有出现另一个异常,会直接导致程序退出。
- 20170226C++项目班05_C/C++错误异常处理
- 【C++】错误处理和异常处理
- 【C++】错误处理和异常处理
- C++【错误和异常的处理】
- 【异常/错误处理系列】C语言如何实现异常处理
- c#中的异常处理
- 异常处理 - [C++]
- c异常处理
- Objective-c异常处理
- C语言异常处理
- c 异常处理
- C 异常处理设计
- [C++] 异常处理
- C++“异常处理”
- objective-c 异常处理
- 【C++】栈空栈满异常处理
- C++:异常处理
- c++_10: 异常处理
- TCP/IP协议 之IPV4与IPV6的区别
- 建造者模式
- Android 利用Sensor现实了传感器
- java 多线程 线程之间的通信
- 设计模式(6)-原型模式
- 20170226C++项目班05_C/C++错误异常处理
- ffmpeg移植android编译问题解决
- Helix浅谈算式处理(C++计算器源码发布)
- 被说了很多遍的设计模式---命令模式
- 基础练习 01字串
- hdu2841 Visible Trees(容斥原理)
- 欢迎使用CSDN-markdown编辑器
- 形态学在图像处理中的应用
- web常用小技术集合