学习->C++篇十八:一文总结C++的异常

目录

C++为什么要引入异常?

什么是异常?

怎么使用异常处理错误?

异常的抛出规则:

异常的匹配规则:

单个catch语句,不能完全处理掉异常?重新抛出异常

什么是异常安全问题?

什么会导致异常安全问题?

异常规范有何作用?怎么做?

何为异常体系?

总结C++异常的优缺点

优点

缺点


C++为什么要引入异常?

首先看C语言传统处理错误的方式,主要有两种:

1.用assert,当不满足条件的时候直接终止程序,缺陷是用户难以接受

2.返回错误码,很多系统调用都是把错误码放在了errno中,缺点是需要程序员自己去用错误码获取错误信息,比如strerror(errno)

为了更好地处理错误,C++引入异常。

什么是异常?

异常:异常是一种处理错误的方式,当函数发现自己无法处理错误的时候,就可以抛出异常,函数的直接调用者或者间接调用者可以捕获这个异常,从而去处理这个错误。

怎么使用异常处理错误?

C++处理异常的三个关键字

throw catch try

语法格式:

try
{
  // 保护的标识代码
}catch( ExceptionName e1 )
{
  // catch 块
}catch( ExceptionName e2 )
{
  // catch 块
}catch( ExceptionName eN )
{
  // catch 块
}

异常的抛出规则:

- 抛出的对象类型决定了哪一个catch语句捕获异常

- 处理代码是与抛出类型匹配,而且离抛异常位置最近的那一块

- 抛出异常对象后,因为抛出的异常对象可能是一个临时的对象,所以捕获异常的语句会生成一个拷贝的对象,在catch语句之后就会销毁这个拷贝的对象

- catch(...)可以捕获任意类型的异常

- 可以抛出派生类对象使用基类类型捕获

异常的匹配规则:

- 首先检查本身是否在try语句块内部,如果是就查找相应的catch语句,如果有匹配就在其地方处理

- 然后没有匹配到catch则退出当前的函数栈,在调用函数的栈中查找匹配的catch

- 当达到主函数main的栈还没有匹配成功时,就会终止程序

- 找到匹配的catch语句并处理之后,就会往catch语句后面继续执行

简单代码理解一下调用函数栈:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>

using std::cout;
using std::endl;

void fun2()
{
	throw 100;
	cout << "fun2" << endl;
}

void fun1()
{
	fun2();
}

int main()
{
	try {
		fun1();
	}
	catch (int a)
	{
		cout << "捕获异常a:" << a << endl;
	}
	catch (...)
	{
		printf("捕获任意类型的异常\n");
	}
	return 0;
}

输出:

单个catch语句,不能完全处理掉异常?重新抛出异常

- 当单个catch语句,不能完全处理掉异常,在经过一些处理之后想交给外层调用的函数再来处理,catch语句块中就可以通过throw;重新抛出异常传递给更上层的函数处理异常

什么是异常安全问题?

由于抛异常导致的资源安全问题

什么会导致异常安全问题?

构造函数中抛出异常,可能导致对象没有完全初始化或者对象不完整

析构函数完成资源的清理,最好不要在其中抛出异常,否则可能导致资源泄露

在new和delete当中抛出异常导致内存泄露,在lock和unlock之间抛出异常导致死锁,C++用来RAII 思想来解决上述问题

异常规范有何作用?怎么做?

目的是为了让函数的使用者知道有可能抛出的异常有哪些类型,在函数后面加(类型),列出函数可能抛出的所有异常的类型

函数后面接throw()表示不抛异常

如果没有异常接口的声明,则此函数可以抛任何类型的异常

C++新增关键字noexcept表示不会抛异常

何为异常体系?

简单而言是一套继承体系,子类直接或间接派生自同一基类。

自定义异常体系:制订一套继承规范体系,大家都抛出的是继承于同一个基类的派生类对象,只要捕获基类类型就可以了

C++标准库的异常体系

总结C++异常的优缺点

优点

- 相比于错误码的方式,可以更清晰的展示出错误信息,可以更好的定位错误

- 返回错误码的方式在函数调用链当中得层层返回错误,最外层才能拿到错误,但是抛异常则可以一次性跳到最外层

- 使用许多的第三方库需要使用异常

- 部分函数使用异常更好处理,比如T& operator这样的不确定返回值类型的函数

缺点

- 抛异常可能会导致执行流乱跳,导致执行流非常混乱,使跟踪调试分析程序的时候比较困难

- C++没有垃圾回收机制,有了异常之后,可能导致资源泄露等问题,即异常安全问题需要使用RAII来处理资源管理问题,有一定学习成本

- C++标准库异常体系定义的不好,自定义的异常体系较多,较为混乱

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值