博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++异常总结
阅读量:6813 次
发布时间:2019-06-26

本文共 2924 字,大约阅读时间需要 9 分钟。

堆栈辗转开解(stack-unwinding):如果一个函数中出现异常,在当前函数内即通过 try..catch 捕捉(且捕捉到)的话,可以继续往下执行;如果不捕捉(或未捕捉到)就会抛出(与通过 throw 显式抛出效果相同)到外层函数,则当前函数会终止运行,释放当前函数内的局部对象(局部对象的析构函数就自然被调用了),外层函数如果也没有捕捉到的话,会再次抛出到更外层的函数,该外层函数也会退出,释放其局部对象……如此一直循环下去,直到找到匹配的 catch 子句,如果找到 main 函数中仍找不到,则调用名为 terminate 的标准库函数,该函数在 exception 头文件中定义,导致程序非正常退出。可以通过 std::set_terminate(fun) 来指定 terminate 调用的函数来输出一些信息。

异常是通过抛出对象而引发的,抛出的对象类型决定应该激活哪个处理代码,被选中的处理代码是距离抛出异常最近的匹配的 catch 子句。

#include 
#include
void fun1() { throw "this is char* exception"; }void fun2() { throw std::string("this is string exception"); }int main(){ try { fun1(); } catch(const char* e) { std::cout<
<

 

标准库异常类:

1、#include <exception>    

定义了最常见的异常类,类名是 exception ,这个类只通知异常的产生,不提供更多信息。被 <stdexcept> 头文件包含

2、#include <stdexcept>

定义了几种常见的异常类,如: exception,runtime_error,range_error,out_of_range 等,都是 exception 的子孙类。

3、#include <new>

定义了 bad_alloc 异常类

4、#include <type_info>

定义了 bad_cast 异常类

标准异常类型只定义了 what() 函数,返回 const char* 字符串,用来提供详细的异常描述信息。what() 返回什么,是由标准异常类的构造函数决定的,像 exception, bad_alloc, bad_cast 类型只有默认构造函数,所以错误信息是不可定制的,而其它标准异常类如 runtime_error 只定义了一个带 string 参数的构造函数,这种异常类型的 what() 就可以在构造函数时定制了。

#include 
#include
void fun() { throw std::runtime_error("this is my runtime_error"); }void fun2() { throw std::exception(); }int main(){ try { fun(); fun2(); }catch(std::runtime_error& e) { std::cout<
<

 

可以自定义异常类,继承 exception ,实现 what() 函数: 

#include 
#include
#include
class MyException : public std::exception{ std::string error_msg;public: explicit MyException(const std::string& _error_msg):error_msg(_error_msg) { } const char* what() { return error_msg.c_str(); } ~MyException() noexcept{} //旧式写法: ~MyException() throw(){} //throw(int) 只能抛出 int 型异常;throw() 不抛出任何异常 //throw() 已经被 c++11 标记为过时,被 noexcept 取代};void fun() { throw MyException("this is myexception"); }int main(){ try { fun(); } catch(MyException& e) { std::cout<
<

不继承 exception 类,也可以使用,那继承它有什么好处呢?

1、统一的规范的接口,what() 函数。

2、可以在捕捉语句中使用 catch(std::exception& e) 来捕捉。    

如果被抛出的异常对象是派生类类型的,但由基类类型的 catch 处理,那么,catch 不能使用派生类的特有的任何成员,也不会有多态行为产生。

另外,通过 catch(...) 可以捕捉所有的异常,包括自定义的异常(也包括不从 exception 继承的异常)。如果这样来看,其实不从 exception 继承也没什么,最后使用 catch(...) 把关。

 

析构函数应该禁止抛出异常,因为当抛出异常时,局部对象析构,而如果此时该局部对象析构函数里也抛出异常的话,则 C++ 无法同时处理两个异常,就会调用 terminate 函数终止程序。如果析构函数里存在异常,应该在析构函数内部处理,而不应当抛出。

构造函数中可以抛出异常,但发生异常时,该对象可能只是部分被构造,由于对象没有构造完成,不会执行析构函数,所以要自己保证能适当的撤销已构造的成员。C++拒绝为没有完成构造函数的对象调用析构函数,原因是避免开销,因为只有在每个对象里加一些字节来记录构造函数执行了多少步,它会使对象变大,且减慢析构函数的运行速度。所以只能自己手动进行资源释放,比较麻烦。一般建议不要在构造函数里做过多的资源分配,而应该把这些操作放在一个类似于 init 的成员函数中去完成。这样当 init 成员函数抛出异常时,如果对象是在栈上,析构函数仍会被调用(异常会自动销毁局部对象,调用局部对象的析构函数),如果是在堆上,需要在捕获异常之后 delete 对象来调用析构函数。

 

在 catch 子句中,可以通过 throw; 重新抛出异常。

转载地址:http://fpwzl.baihongyu.com/

你可能感兴趣的文章
如何使用Nginx对抗DDoS攻击?
查看>>
PHP错误:SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client
查看>>
车载摄像头 原像 镜像
查看>>
shell 在手分析服务器日志【转】
查看>>
简单理解Linux的Loopback接口
查看>>
nethogs 按进程实时统计网络带宽利用率的工具
查看>>
ubuntu svn 安装 http访问配置, https 访配置 ldap 验证配置
查看>>
java 网站用户在线和客服聊天
查看>>
订单系统开发(仿淘宝和美团网) 之 项目总结(一)
查看>>
django中的null=true,blank=true,这个讲得清楚点
查看>>
Mysql的存储过程(以Mysql为例进行讲解)
查看>>
深入浅出JSON[转]
查看>>
C#使用ICSharpCode.SharpZipLib压缩文件[转]
查看>>
用vc++如何得到汉字的Unicode编码?
查看>>
(原創) HDL只是代表一個model (IC Design) (Verilog)
查看>>
System.Net.Mail 例子 [收藏]
查看>>
WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
查看>>
C语言 return没有返回值.
查看>>
超级详细Tcpdump 的用法
查看>>
JAVA的String 类
查看>>