堆栈辗转开解(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++异常总结的更多相关文章

  1. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  2. ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”

    在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...

  3. 记一次tomcat线程创建异常调优:unable to create new native thread

    测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...

  4. 使用JSONObject.fromObject的时候出现“There is a cycle in the hierarchy”异常 的解决办法

    在使用JSONObject.fromObject的时候,出现“There is a cycle in the hierarchy”异常.   意思是出现了死循环,也就是Model之间有循环包含关系: ...

  5. SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论

    异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...

  6. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  7. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  8. [C#] C# 知识回顾 - 学会使用异常

    学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...

  9. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

  10. 基于AOP的MVC拦截异常让代码更优美

    与asp.net 打交道很多年,如今天微软的优秀框架越来越多,其中微软在基于mvc的思想架构,也推出了自己的一套asp.net mvc 框架,如果你亲身体验过它,会情不自禁的说‘漂亮’.回过头来,‘漂 ...

随机推荐

  1. 【bzoj1912】 Apio2010—patrol 巡逻

    http://www.lydsy.com/JudgeOnline/problem.php?id=1912 (题目链接) 题意 给出一棵树,要求在树上添加K(1 or 2)条边,添加的边必须经过一次,使 ...

  2. 【poj1987】 Distance Statistics

    http://poj.org/problem?id=1987 (题目链接) 题意 给出一棵树,求树上距离不超过K的点对个数. Solution 点分治,同poj1741. 代码 // poj1987 ...

  3. 【poj3342】 Party at Hali-Bula

    http://poj.org/problem?id=3342 (题目链接) 题意 给出一棵树,要求在不存在两个节点相邻的条件下,选出尽可能多的节点,并且判断是否有多种选法. Solution 很水的树 ...

  4. Jenkins配置的邮件无法发送的问题

    一.不要使用系统默认的插件,请使用[Extended E-mail Notification] 二.一下的选项要和你发邮件人填写的保持一致

  5. C# winform窗体设计-通过条件查询数据

    在winform 数据库设计中,有时候需要通过条件查询对应的数据,并且将数据显示在文本框(or 富文本框)中,下面,小编将讲述通过一个条件: 首先,我们需要对数据库建立连接,并且执行数据库命令,在此之 ...

  6. Codeforces Round #389 Div.2 E. Santa Claus and Tangerines

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

  7. SaltStack与ZeroMQ(二)

    SaltStack与ZeroMQ SaltStack底层是基于ZeroMQ进行高效的网络通信. ZeroMQ简介 ØMQ (也拼写作ZeroMQ,0MQ或ZMQ)是一个为可伸缩的分布式或并发应用程序设 ...

  8. Can not issue data manipulation statements with executeQuery() 异常处理

    1.这个异常的报错翻译过来就是 不能发出数据操纵语句与executeQuery() 2.这里要检查一下你要执行的实际SQL语句要做什么操作 查询呢?还是修改? 3.如果是修改的话,需要添加@Modif ...

  9. vm centos 添加网卡 无配置文件

    vm centos 添加网卡 无配置文件 解决办法 [root@test ~]# ifconfig eth0 Link encap:Ethernet HWaddr 00:0C:29:C8:41:FB ...

  10. Java数据结构——双向链表

    //================================================= // File Name : DoublyLinked_demo //------------- ...