【C++】异常

前言

本篇博客我们来看下C++有关异常的处理,了解下异常有关的知识

💓 个人主页:小张同学zkf

⏩ 文章专栏:C++

若有问题 评论区见📝

🎉欢迎大家点赞👍收藏⭐文章 ​

目录

1.异常的概念及使用

 1.1异常的概念

1.2异常的抛出和捕获

1.3栈展开

1.4查找匹配的处理代码

1.5异常重新抛出

 1.6异常安全问题

1.7异常规范

2.标准库的异常


1.异常的概念及使用

 1.1异常的概念

异常处理机制允许程序中独⽴开发的部分能够在运⾏时就出现的问题进⾏通信并做出相应的处理,
异常使得我们能够将问题的检测与解决问题的过程分开,程序的⼀部分负责检测问题的出现,然后
解决问题的任务传递给程序的另⼀部分,检测环节⽆须知道问题的处理模块的所有细节。
C语⾔主要通过错误码的形式处理错误,错误码本质就是对错误信息进⾏分类编号,拿到错误码以
后还要去查询错误信息,⽐较⿇烦。异常时抛出⼀个对象,这个对象可以函数更全⾯的各种信息。

1.2异常的抛出和捕获

程序出现问题时,我们通过抛出(throw)⼀个对象来引发⼀个异常,该对象的类型以及当前的调⽤
链决定了应该由哪个catch的处理代码来处理该异常。
被选中的处理代码是调⽤链中与该对象类型匹配且离抛出异常位置最近的那⼀个。根据抛出对象的
类型和内容,程序的抛出异常部分告知异常处理部分到底发⽣了什么错误。
当throw执⾏时,throw后⾯的语句将不再被执⾏。程序的执⾏从throw位置跳到与之匹配的catch
模块,catch可能是同⼀函数中的⼀个局部的catch,也可能是调⽤链中另⼀个函数中的catch,控
制权从throw位置转移到了catch位置。这⾥还有两个重要的含义:1、沿着调⽤链的函数可能提早
退出。2、⼀旦程序开始执⾏异常处理程序,沿着调⽤链创建的对象都将销毁。
抛出异常对象后,会⽣成⼀个异常对象的拷⻉,因为抛出的异常对象可能是⼀个局部对象,所以会
⽣成⼀个拷⻉对象,这个拷⻉的对象会在catch⼦句后销毁。(这⾥的处理类似于函数的传值返
回)

1.3栈展开

抛出异常后,程序暂停当前函数的执⾏,开始寻找与之匹配的catch⼦句,⾸先检查throw本⾝是否
在try块内部,如果在则查找匹配的catch语句,如果有匹配的,则跳到catch的地⽅进⾏处理。
如果当前函数中没有try/catch⼦句,或者有try/catch⼦句但是类型不匹配,则退出当前函数,继续
在外层调⽤函数链中查找,上述查找的catch过程被称为栈展开。
如果到达main函数,依旧没有找到匹配的catch⼦句,程序会调⽤标准库的 terminate 函数终⽌
程序。
如果找到匹配的catch⼦句处理后,catch⼦句代码会继续执⾏。

double Divide ( int a, int b)
{
try
{
// b == 0 时抛出异常
if (b == 0 )
{
string s ( "Divide by zero condition!" );
throw s;
}
else
{
return (( double )a / ( double )b);
}
}
catch ( int errid)
{
cout << errid << endl;
}
return 0 ;
}
void Func ()
{
int len, time;
cin >> len >> time;
try
{
cout << Divide (len, time) << endl;
}
catch ( const char * errmsg)
{
cout << errmsg << endl;
}
cout <<__FUNCTION__<< ":" << __LINE__ << " ⾏执⾏ " << endl;
}
int main ()
{
while ( 1 )
{
try
{
Func ();
}
catch ( const string& errmsg)
{
cout << errmsg << endl;
}
}
return 0 ;
}

1.4查找匹配的处理代码

⼀般情况下抛出对象和catch是类型完全匹配的,如果有多个类型匹配的,就选择离他位置更近的
那个。
但是也有⼀些例外,允许从⾮常量向常量的类型转换,也就是权限缩⼩;允许数组转换成指向数组
元素类型的指针,函数被转换成指向函数的指针;允许从派⽣类向基类类型的转换,这个点⾮常实
⽤,实际中继承体系基本都是⽤这个⽅式设计的。
如果到main函数,异常仍旧没有被匹配就会终⽌程序,不是发⽣严重错误的情况下,我们是不期望程序终⽌的,所以⼀般main函数中最后都会使⽤catch(...),它可以捕获任意类型的异常,但是是
不知道异常错误是什么。
1 # include <thread>
2
3 // ⼀般⼤型项⽬程序才会使⽤异常,下⾯我们模拟设计⼀个服务的⼏个模块
4 // 每个模块的继承都是 Exception 的派⽣类,每个模块可以添加⾃⼰的数据
5 // 最后捕获时,我们捕获基类就可以
6 class Exception
7 {
8 public :
9 Exception ( const string& errmsg, int id)
10 :_errmsg(errmsg)
11 , _id(id)
12 {}
13
14 virtual string what () const
15 {
16 return _errmsg;
17 }
18
19 <
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值