c++异常总结
堆栈辗转开解(stack-unwinding):如果一个函数中出现异常,在当前函数内即通过 try..catch 捕捉(且捕捉到)的话,可以继续往下执行;如果不捕捉(或未捕捉到)就会抛出(与通过 throw 显式抛出效果相同)到外层函数,则当前函数会终止运行,释放当前函数内的局部对象(局部对象的析构函数就自然被调用了),外层函数如果也没有捕捉到的话,会再次抛出到更外层的函数,该外层函数也会退出,释放其局部对象……如此一直循环下去,直到找到匹配的 catch 子句,如果找到 main 函数中仍找不到,则调用名为 terminate 的标准库函数,该函数在 exception 头文件中定义,导致程序非正常退出。可以通过 std::set_terminate(fun) 来指定 terminate 调用的函数来输出一些信息。
异常是通过抛出对象而引发的,抛出的对象类型决定应该激活哪个处理代码,被选中的处理代码是距离抛出异常最近的匹配的 catch 子句。
#include <iostream>
#include <string> 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<<e<<std::endl;
}
try
{
fun2();
}
catch(std::string& e)
{
std::cout<<e<<std::endl;
}
}
标准库异常类:
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 <iostream>#include <stdexcept>
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<<e.what()<<std::endl;
}
catch(std::exception& e)
{
std::cout<<e.what()<<std::endl;
}
}
可以自定义异常类,继承 exception ,实现 what() 函数:
#include <iostream>
#include <string>
#include <exception> 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<<e.what()<<std::endl;
}
}
不继承 exception 类,也可以使用,那继承它有什么好处呢?
1、统一的规范的接口,what() 函数。
2、可以在捕捉语句中使用 catch(std::exception& e) 来捕捉。
如果被抛出的异常对象是派生类类型的,但由基类类型的 catch 处理,那么,catch 不能使用派生类的特有的任何成员,也不会有多态行为产生。
另外,通过 catch(...) 可以捕捉所有的异常,包括自定义的异常(也包括不从 exception 继承的异常)。如果这样来看,其实不从 exception 继承也没什么,最后使用 catch(...) 把关。
析构函数应该禁止抛出异常,因为当抛出异常时,局部对象析构,而如果此时该局部对象析构函数里也抛出异常的话,则 C++ 无法同时处理两个异常,就会调用 terminate 函数终止程序。如果析构函数里存在异常,应该在析构函数内部处理,而不应当抛出。
构造函数中可以抛出异常,但发生异常时,该对象可能只是部分被构造,由于对象没有构造完成,不会执行析构函数,所以要自己保证能适当的撤销已构造的成员。C++拒绝为没有完成构造函数的对象调用析构函数,原因是避免开销,因为只有在每个对象里加一些字节来记录构造函数执行了多少步,它会使对象变大,且减慢析构函数的运行速度。所以只能自己手动进行资源释放,比较麻烦。一般建议不要在构造函数里做过多的资源分配,而应该把这些操作放在一个类似于 init 的成员函数中去完成。这样当 init 成员函数抛出异常时,如果对象是在栈上,析构函数仍会被调用(异常会自动销毁局部对象,调用局部对象的析构函数),如果是在堆上,需要在捕获异常之后 delete 对象来调用析构函数。
在 catch 子句中,可以通过 throw; 重新抛出异常。
c++异常总结的更多相关文章
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”
在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...
- 记一次tomcat线程创建异常调优:unable to create new native thread
测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...
- 使用JSONObject.fromObject的时候出现“There is a cycle in the hierarchy”异常 的解决办法
在使用JSONObject.fromObject的时候,出现“There is a cycle in the hierarchy”异常. 意思是出现了死循环,也就是Model之间有循环包含关系: ...
- SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论
异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- [C#] C# 知识回顾 - 学会处理异常
学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...
- [C#] C# 知识回顾 - 学会使用异常
学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...
- [C#] C# 知识回顾 - 异常介绍
异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...
- 基于AOP的MVC拦截异常让代码更优美
与asp.net 打交道很多年,如今天微软的优秀框架越来越多,其中微软在基于mvc的思想架构,也推出了自己的一套asp.net mvc 框架,如果你亲身体验过它,会情不自禁的说‘漂亮’.回过头来,‘漂 ...
随机推荐
- 【uoj264】 NOIP2016—蚯蚓
http://uoj.ac/problem/264 (题目链接) 题意 n条蚯蚓,时间为m.每单位时间要可以将最长的蚯蚓切成len/2和len-len/2两份,长度为0的蚯蚓不会消失,因为每单位时间所 ...
- JQuery实现页面刷新滚动条自动滚动到特定位置
var cotentOffset = $('#6f').offset(); $('.info_box').animate({ scrollLeft: cotentOffset.left }, ); 原 ...
- bos启动56898服务器配置界面报错
//文件路径 /easweb/runtime/server/deploy/portal.ear/portal.war/WEB-INF/config/spring/applicationContext- ...
- React Native 开发之 (07) 常用组件-View
掌握了React Native的组件就可以使用IOS的原生组件和API. 一 View组件 就像开发web应用程序中,需要使用很多的HTML标签.例如 div,form.但是在基于DIV+CSS布局的 ...
- python3,交互模式,无法使用ctrl和方向键,需要和ctrl一块用
转自csdn博客 http://blog.csdn.net/pumaadamsjack/article/details/52447989 https://pypi.python.org/pypi/re ...
- uC/OS-II队列(OS_q)块
/*************************************************************************************************** ...
- geoip scala api
#!/bin/bash /home/hadoop/spark-1.6.2/bin/spark-shell --master spark://hbase11:7077 --executor-memory ...
- centos6.5yum方式升级内核
升级内核需要使用elrepo的yum源,在安装yum源之前还需要我们导入elrepo的key,如下:rpm -import https://www.elrepo.org/RPM-GPG-KEY-elr ...
- Python + OpenCV2 系列:2 - 图片操作
这些相当于我的学习笔记,所以并没有很强的结构性和很全的介绍,请见谅. 1 读取.写入图像 下面是一个简短的载入图像.打印尺寸.转换格式及保存图像为.png的例子: # -*- coding: utf- ...
- Flash Builder 4.7 破解
http://litech.diandian.com/post/2013-03-22/40049178994 Adobe Flash Builder 4.7 For Mac 破解 和Photoshop ...