[c++] Exceptions
异常处理
一、相关资料
[ 之后,针对本章节、根据链接再进行一次系统的学习 ]
基本结构
try {
throw logic_error{"blah"};
} catch (exception) {
// caught here!
} catch (logic_error) {
// not here!
}
百家讲坛 - "必要性"
[1]
为什么需要异常机制:https://blog.csdn.net/K346K346/java/article/details/50087193
C++之父Bjarne Stroustrup在《The C++ Programming Language》中讲到:
(a) 一个库的作者可以检测出发生了运行时错误,但一般不知道怎样去处理它们(因为和用户具体的应用有关);
(b) 另一方面,库的用户知道怎样处理这些错误,但却无法检查它们何时发生(如果能检测,就可以在用户的代码里处理了,不用留给库去发现)。
Bjarne Stroustrup说:提供异常的基本目的就是为了处理上面的问题。基本思想是:让一个函数在发现了自己无法处理的错误时抛出(throw)一个异常,然后它的(直接或者间接)调用者能够处理这个问题。
[2]
C++ 引入异常的原因之一是:为了能让构造函数报错(析构函数不能抛异常这是大家都知道的常识),毕竟构造函数没有返回值,没有异常的话调用方如何得知对象构造是否成功呢?
[3]
到了异常,一般就直接让本次操作失效,保存状态好了.
定义异常
一、内置 Error类型
下表是对上面层次结构中出现的每个异常的说明:
异常 | 描述 |
---|---|
std::exception | 该异常是所有标准 C++ 异常的父类。 |
std::bad_alloc | 该异常可以通过 new 抛出。 |
std::bad_cast | 该异常可以通过 dynamic_cast 抛出。 |
std::bad_exception | 这在处理 C++ 程序中无法预期的异常时非常有用。 |
std::bad_typeid | 该异常可以通过 typeid 抛出。 |
std::logic_error | 理论上可以通过读取代码来检测到的异常。 |
- std::domain_error | 当使用了一个无效的数学域时,会抛出该异常。 |
- std::invalid_argument | 当使用了无效的参数时,会抛出该异常。 |
- std::length_error | 当创建了太长的 std::string 时,会抛出该异常。 |
- std::out_of_range | 该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator[]()。 |
std::runtime_error | 理论上不可以通过读取代码来检测到的异常。 |
- std::overflow_error | 当发生数学上溢时,会抛出该异常。 |
- std::range_error | 当尝试存储超出范围的值时,会抛出该异常。 |
- std::underflow_error | 当发生数学下溢时,会抛出该异常。 |
二、自定义异常类型
通过继承和重载 exception 类来定义新的异常。
#include <iostream>
#include <exception>
using namespace std;
// 竟然是个struct
struct MyException : public exception
{
const char* what () const throw
{
return "C++ Exception";
}
}; // -------------------------------------------------
int main()
{
try
{
throw MyException();
}
catch(MyException& e)
{
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
catch(std::exception& e)
{
// 其他的错误
}
}
类可以继承,结构体也可以继承.
#include <iostream>
using namespace std;
//
class MyException : public exception
{
public:
const char* what() const throw () // <----
{
std::cout << "my exception" << std::endl;
return NULL;
}
}; void f1(bool flag = true)
{
if (flag) throw MyException();
} void f2(bool flag = true) throw ()
{
if (flag) throw MyException();
}
----------------------------------------------------- int main(void)
{
try
{
f1();
}
catch (...)
{
;
}
std::cout << "f1()异常将被捕获,不会 abort,将继续执行" << std::endl; try
{
f2();
}
catch (...)
{
;
}
std::cout << "f2()异常不会被捕获,程序将会 abort,将不会执行该条语句" << std::endl; return ;
}
使用异常
Catch-by-reference is BETTER
Problems with Catch-by-value:
- inefficient due to object copying
- causes the slicing problem, and
- cannot exploit polymorphism and dynamic binding
Catch-by-reference avoids all these problems.
catch的参数是引用,自然就不需要拷贝了。
Catch-by-Value
#include <iostream> using namespace std; class X {
public:
X() {
std::cout << "X constructed" << std::endl;
} X(const X &x) {
std::cout << "X copy-constructed" << std::endl;
} ~X() {
std::cout << "X destructed" << std::endl;
}
};
void g() {
throw X{};
} void f() {
try {
g();
} catch (X x) { // 改为catch(X &x), 其他同理
std::cout << "caught in f; rethrow" << std::endl;
throw;
}
}
int main()
{
cout << "Hello World!" << endl; try {
f();
} catch (X x) { // 这里又是一次 浪费时间的 copy
std::cout << "caught in main" << std::endl;
} return ;
}
Result:
Catch-by-Reference
改为reference后,concise了不少!
Stack Unwinding
关于new object这件事上,Obversely, this avoids memory leaks but is messy.
便有了Smart Pointer? 这里是初始化列表的用法。
Stack Exception Safety
如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()函数来终止程序的运行,这比基于异常机制的throw()在效率上会高一些。
这是因为异常机制会带来一些额外开销,比如函数抛出异常,会导致函数栈被依次地展开(unwind),并依帧调用在本帧中已构造的自动变量的析构函数等。
Common Levels of Exception Safety
End.
[c++] Exceptions的更多相关文章
- "NHibernate.Exceptions.GenericADOException: could not load an entity" 解决方案
今天,测试一个项目的时候,抛出了这个莫名其妙的异常,然后就开始了一天的调试之旅... 花了很长时间,没有从代码找出任何问题... 那么到底哪里出问题呢? 根据下面那段长长的错误日志: -- ::, ...
- 2000条你应知的WPF小姿势 基础篇<34-39 Unhandled Exceptions和Resource>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'dd' in 'where clause'
今天在使用mysql数据库查找数据的时候报错,错误信息如下: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown co ...
- MIT 6.828 JOS学习笔记18. Lab 3.2 Part B: Page Faults, Breakpoints Exceptions, and System Calls
现在你的操作系统内核已经具备一定的异常处理能力了,在这部分实验中,我们将会进一步完善它,使它能够处理不同类型的中断/异常. Handling Page Fault 缺页中断是一个非常重要的中断,因为我 ...
- Solve VS2010 Error "Exceptions has been thrown by the target of an invocation"
Sometimes when you open a VS2010 project, an error window will pop up with the error message "E ...
- MyBatis-Exception:org.apache.ibatis.exceptions.PersistenceException
错误信息如下: HTTP Status 500 - org.mybatis.spring.MyBatisSystemException: nested exception is org.apache. ...
- App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file
ios进行http请求,会出现这个问题: App Transport Security has blocked a cleartext HTTP (http://) resource load sin ...
- 添加 All Exceptions 断点后, 每次运行都会在 main.m 中断的一种解决方法
在本人项目添加导入和使用新的字体过程中,遇到一个很奇怪的问题: 项目开启了全局断点,但是每次启动都会运行在mian.m中断,点击下一步程序继续正常运行. 不知道是什么原因,于是google百度寻找答案 ...
- python基于Django框架编译报错“django.core.exceptions.ImproperlyConfigured”的解决办法?
下面是我具体遇到的问题和解决方法: 错误详细信息: django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_IND ...
- Rethrowing exceptions and preserving the full call stack trace
refer:http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the- ...
随机推荐
- Paket 介绍
在国外.NET社区有一个很火的话题是Packet(https://fsprojects.github.io/Paket/index.html ),它本质上是Nuget 之外的另一种方式管理.NET项目 ...
- Xamarin.Forms 免费电子书
Xamarin Evolve 正在举行,现在已经放出2本免费的Xamarin.Forms 免费电子书,据现场的同学说这两天还有Xamarin.Forms 重磅消息发布: Creating Mobile ...
- ABP理论学习之验证DTO
返回总目录 本篇目录 验证介绍 使用数据注解 自定义验证 标准化 验证介绍 首先应该验证应用的输入.用户或者其它应用都可以向该应用发送输入.在一个web应用中,验证通常要实现两次:在客户端和服务器端. ...
- (DNS被劫持所导致的)QQ音乐与视频网页打开很慢的解决方法
这周开始发现一个很让人抓狂的现象,QQ音乐网页(http://y.qq.com)与QQ视频(http://v.qq.com/)网页打开超慢,甚至是无法打开,严重影响了业余的音乐视频生活. 以QQ视频为 ...
- 大白话讲解Promise(一)
去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ...
- [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写
一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...
- 用python实现的百度音乐下载器-python-pyqt-改进版
之前写过一个用python实现的百度新歌榜.热歌榜下载器的博文,实现了百度新歌.热门歌曲的爬取与下载.但那个采用的是单线程,网络状况一般的情况下,扫描前100首歌的时间大概得到40来秒.而且用Pyqt ...
- Module-Zero之版本管理
返回<Module Zero学习目录> 概要介绍 版本实体 版本管理者 概要介绍 绝大多数的SaaS(多租户)应用都有多个具有不同特征的版本(包).因此,他们可以给租户(即客户)提供不同的 ...
- Module-Zero之发布说明
返回<Module Zero学习目录> ABP v0.7.6.0 创建组织单元系统. 升级了nuget包. 小修复和改进. 注意: AbpUserManager的构造函数更新了.添加了组织 ...
- 每天一个linux命令(48):watch命令
watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行.在Linux下,watch是周期性的执行下个 ...