转载:https://blog.csdn.net/fcsfcsfcs/article/details/77717567

catch(…)能够捕获多种数据类型的异常对象,所以它提供给程序员一种对异常 对象更好的控制手段,使开发的软件系统有很好的可靠性
 

如果要想使一个catch block能抓获多种数据类型的异常对象的话,怎么办?C++标准中定义了一种特殊的catch用法,那就是” catch(…)”。 
感性认识

1、catch(…)到底是一个什么样的东东,先来个感性认识吧!
看例子先:

复制代码代码如下:

 int main() 
{ 
try 
{ 
cout << "在 try block 中, 准备抛出一个异常." << endl; 
//这里抛出一个异常(其中异常对象的数据类型是int,值为1) 
throw 1; 
} 
//catch( int& value ) 
//注意这里catch语句 
catch( …) 
{ 
cout << "在 catch(…) block 中, 抛出的int类型的异常对象被处理" << endl; 
} 
}

2、哈哈!int类型的异常被catch(…)抓获了,再来另一个例子:

复制代码代码如下:

 int main() 
{ 
try 
{ 
cout << "在 try block 中, 准备抛出一个异常." << endl; 
//这里抛出一个异常(其中异常对象的数据类型是double,值为0.5) 
throw 0.5; 
} 
//catch( double& value ) 
//注意这里catch语句 
catch( …) 
{ 
cout << "在 catch(…) block 中, double类型的异常对象也被处理" << endl; 
} 
}

3、同样,double类型的异常对象也被catch(…)块抓获了。是的,catch(..)能匹配成功所有的数据类型的异常对象,包括C++语言提 供所有的原生数据类型的异常对象,如int、double,还有char*、int*这样的指针类型,另外还有数组类型的异常对象。同时也包括所有自定义 的抽象数据类型。例程如下:

复制代码代码如下:

 int main() 
{ 
try 
{ 
cout << "在 try block 中, 准备抛出一个异常." << endl; 
//这里抛出一个异常(其中异常对象的数据类型是char*) 
char* p=0; 
throw p; 
} 
//catch( char* value ) 
//注意这里catch语句 
catch( …) 
{ 
cout << "在 catch(…) block 中, char*类型的异常对象也被处理" << endl; 
} 
} 
int main() 
{ 
try 
{ 
cout << "在 try block 中, 准备抛出一个异常." << endl; 
//这里抛出一个异常(其中异常对象的数据类型是int[]) 
int a[4]; 
throw a; 
} 
//catch( int value[] ) 
//注意这里catch语句 
catch( …) 
{ 
cout << "在 catch(…) block 中, int[]类型的异常对象也被处理" << endl; 
} 
}

4、对于抽象数据类型的异常对象。catch(…)同样有效,例程如下:

复制代码代码如下:

 class MyException 
{ 
public: 
protected: 
int code; 
}; 
int main() 
{ 
try 
{ 
cout << "在 try block 中, 准备抛出一个异常." << endl; 
//这里抛出一个异常(其中异常对象的数据类型是MyException) 
throw MyException(); 
} 
//catch(MyException& value ) 
//注意这里catch语句 
catch( …) 
{ 
cout << "在catch(…) block中, MyException类型的异常对象被处理" << endl; 
} 
}

对catch(…)有点迷糊?
1、究竟对catch(…)有什么迷糊呢?还是看例子先吧!

复制代码代码如下:

void main() 
{ 
int* p = 0; 
try 
{ 
// 注意:下面这条语句虽然不是throw语句,但它在执行时会导致系统 
// 出现一个存储保护错误的异常(access violation exception) 
*p = 13; // causes an access violation exception; 
} 
catch(...) 
{ 
//catch(…)能抓获住上面的access violation exception异常吗? 
cout << "在catch(…) block中" << endl; 
} 
}

请问上面的程序运行时会出现什么结果吗?catch(…)能抓获住系统中出现的access violation exception异常吗?朋友们!和我们的主人公阿愚一样,自己动手去测试一把!

结果又如何呢?实际上它有两种不同的运行结果,在window2000系统下用VC来测试运行这个小程序时,发现程序能输出"在catch(…) block中"的语句在屏幕上,也即catch(…) 能成功抓获住系统中出现的access violation exception异常,很厉害吧!但如果这个同样的程序在linux下用gcc编译后运行时,程序将会出现崩溃,并在屏幕上输出”segment fault”的错误信息。

主人公阿愚有点急了,也开始有点迷糊了,为什么?为什么?为什么同样一个程序在两种不同的系统上有不同的表现呢?其原因就是:对于这种由于硬件或操作 系统出现的系统异常(例如说被零除、内存存储控制异常、页错误等等)时,window2000系统有一个叫做结构化异常处理(Structured Exception Handling,SEH)的机制,这个东东太厉害了,它能和VC中的C++异常处理模型很好的结合上(实际上VC实现的C++异常处理模型很大程度上建 立在SEH机制之上的,或者说它是SEH的扩展,后面文章中会详细阐述并分析这个久富盛名的SEH,看看catch(…)是如何神奇接管住这种系统异常出 现后的程序控制流的,不过这都是后话)。而在linux系统下,系统异常是由信号处理编程方法来控制的(信号处理编程,signal processing progamming。在介绍unix和linux下如何编程的书籍中,都会有对信号处理编程详细的介绍,当然执着的主人公阿愚肯定对它也不会放过,会深 入到unix沿袭下来的信号处理编程内部的实现机制,并尝试完善改进它,使它也能够较好地和C++异常处理模型结合上)。

那么C++标准中对于这种同一个程序有不同的运行结果有何解释呢?这里需要注意的是,window2000系统下catch(…)能捕获住系统异常, 这完全是它自己的扩展。在C++标准中并没有要求到这一点,它只规定catch(…)必须能捕获程序中所有通过throw语句抛出的异常。因此上面的这个 程序在linux系统下的运行结果也完全是符合C++标准的。虽然大家也必须承认window2000系统下对C++异常处理模型的这种扩展确实是一个很 不错的完善,极大得提高了程序的安全性。

为什么要用catch(…)这个东东?
程序员朋友们也许会说,这还有问吗?这篇文章的一开始不就讲到了吗?catch(…)能够捕获多种数据类型的异常对象,所以它提供给程序员一种对异常 对象更好的控制手段,使开发的软件系统有很好的可靠性。因此一个比较有经验的程序员通常会这样组织编写它的代码模块,如下:

复制代码代码如下:

 void Func() 
{ 
try 
{ 
// 这里的程序代码完成真正复杂的计算工作,这些代码在执行过程中 
// 有可能抛出DataType1、DataType2和DataType3类型的异常对象。 
} 
catch(DataType1& d1) 
{ 
} 
catch(DataType2& d2) 
{ 
} 
catch(DataType3& d3) 
{ 
} 
// 注意上面try block中可能抛出的DataType1、DataType2和DataType3三 
// 种类型的异常对象在前面都已经有对应的catch block来处理。但为什么 
// 还要在最后再定义一个catch(…) block呢?这就是为了有更好的安全性和 
// 可靠性,避免上面的try block抛出了其它未考虑到的异常对象时导致的程 
// 序出现意外崩溃的严重后果,而且这在用VC开发的系统上更特别有效,因 
// 为catch(…)能捕获系统出现的异常,而系统异常往往令程序员头痛了,现 
// 在系统一般都比较复杂,而且由很多人共同开发,一不小心就会导致一个 
// 指针变量指向了其它非法区域,结果意外灾难不幸发生了。catch(…)为这种 
// 潜在的隐患提供了一种有效的补救措施。 
catch(…) 
{ 
} 
}

还有,特别是VC程序员为了使开发的系统有更好的可靠性,往往在应用程序的入口函数中(如MFC框架的开发环境下 CXXXApp::InitInstance())和工作线程的入口函数中加上一个顶层的trycatch块,并且使用catch(…)来捕获一切所有的 异常,如下:

复制代码代码如下:

 BOOL CXXXApp::InitInstance() 
{ 
if (!AfxSocketInit()) 
{ 
AfxMessageBox(IDP_SOCKETS_INIT_FAILED); 
return FALSE; 
} 
AfxEnableControlContainer(); 
// Standard initialization 
// If you are not using these features and wish to reduce the size 
// of your final executable, you should remove from the following 
// the specific initialization routines you do not need. 
#ifdef _AFXDLL 
Enable3dControls(); // Call this when using MFC in a shared DLL 
#else 
Enable3dControlsStatic(); // Call this when linking to MFC statically 
#endif 
// 注意这里有一个顶层的trycatch块,并且使用catch(…)来捕获一切所有的异常 
try 
{ 
CXXXDlg dlg; 
m_pMainWnd = &dlg; 
int nResponse = dlg.DoModal(); 
if (nResponse == IDOK) 
{ 
// TODO: Place code here to handle when the dialog is 
// dismissed with OK 
} 
else if (nResponse == IDCANCEL) 
{ 
// TODO: Place code here to handle when the dialog is 
// dismissed with Cancel 
} 
} 
catch(…) 
{ 
// dump出系统的一些重要信息,并通知管理员查找出现意外异常的原因。 
// 同时想办法恢复系统,例如说重新启动应用程序等 
} 
// Since the dialog has been closed, return FALSE so that we exit the 
// application, rather than start the application's message pump. 
return FALSE; 
}

通过上面的例程和分析可以得出,由于catch(…)能够捕获所有数据类型的异常对象,所以在恰当的地方使用catch(…)确实可以使软件系统有着更 好的可靠性。这确实是大家使用catch(…)这个东东最好的理由。但不要误会的是,在C++异常处理模型中,不只有catch(…)方法能够捕获几乎所 有类型的异常对象.

C++ 异常处理 catch(...)介绍的更多相关文章

  1. 132.try throw catch介绍

    #include <iostream> using namespace std; //try尝试执行,抛出throw,throw之后语句不再执行 //catch处理throw的异常 voi ...

  2. Java中的异常处理try catch(第八周课堂示例总结)

    异常处理 使用Java异常处理机制: 把可能会发生错误的代码放进try语句块中. 当程序检测到出现了一个错误时会抛出一个异常对象. 异常处理代码会捕获并处理这个错误. catch语句块中的代码用于处理 ...

  3. Nodejs异步异常处理domain

    前言 程序开发中,最麻烦的事情之一就是异常处理:对于Nodejs程序开发,最麻烦的事情莫过于异步异常处理. 以MVC的多层架构设计角度,异常总是要一层一层向上抛出,最后在客户端出打印错误.但是,Nod ...

  4. [ Java学习基础 ] Java异常处理

    一.异常概述 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的.比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用Sys ...

  5. C和C++中的异常处理

    1.简介 许多的编程新手对异常处理视而不见,程序里很少考虑异常情况.一部分人甚至根本就不考虑,以为程序总是能以正确的途径运行.譬如我们有的程序设计者调用fopen打开一个文件后,立马就开始进行读写操作 ...

  6. 深入了解 Java 中的异常处理 + 面试题

    # 深入了解 Java 中的异常处理 + 面试题 在程序开发中,异常处理也是我们经常使用到的模块,只是平常很少去深究异常模块的一些知识点.比如,try-catch 处理要遵循的原则是什么,finall ...

  7. ASP.NET Core 中间件自定义全局异常处理

    目录 背景 ASP.NET Core过滤器(Filter) ASP.NET Core 中间件(Middleware) 自定义全局异常处理 .Net Core中使用ExceptionFilter .Ne ...

  8. JAVA 异常和异常处理

    目录 一.异常 1.基本概念 2.异常体系图 3.五大运行时异常 4.编译异常 二.异常处理 1.异常处理的方式 1.1try-catch异常处理 注意事项 课堂练习题 1.2throws异常处理 注 ...

  9. PHP中的错误处理、异常处理机制详解

    在编写PHP程序时,错误处理是一个重要的部分.如果程序中缺少错误检测代码,那么看上去很不专业,也为安全风险敞开了大门 例: <?php $a = fopen('test.txt','r'); / ...

随机推荐

  1. oracle的system登不了

    (密码对的,密码错直接就是被拒了) 这个一直弹出改密码 但是改了点[确定],又说 oracle改system密码 [oracle@localhost ~]$ sqlplus / as sysdba S ...

  2. wpf附加属性详解

    为什么使用附加属性 附加属性的一个用途是允许不同的子元素为父元素中定义的属性指定唯一的值. 此方案的一个具体应用是,让子元素通知父元素它们在用户界面 (UI) 中的呈现方式. 一个示例是 DockPa ...

  3. HDU-1754-I Hate It(单点更新+区间查询)

    很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有 ...

  4. [AngstromCTF 2019]Cookie Cutter

    最近看到了一个国外高中生的CTF比赛,翻了一下往年的例题,发现有一道关于jwt session伪造的题比较有意思,记录一下 题目简介中给出了我们题目的地址和后端处理的源码,看看源码先代码审计一下: c ...

  5. Mysql慢查询(分析工具)

    慢查询分析工具[mysqldumpslow] 常用的慢查询日志分析工具 汇总除查询条件外其他完全相同的SQL,并将分析结果按照参数中所指定的顺序输出 语法: mysqldumpslow -s r -t ...

  6. 自定义线程池ThreadPoolExecutor

    使用自定义的方式创建线程池 Java本身提供的获取线程池的方式 使用Executors直接获取线程池,注意,前四个方式的底层都是通过new ThreadPoolExecutor()的方式创建的线程池, ...

  7. 使用jackson解析json串得到树模型,然后遍历树模型获得需要的数据

    Problem:从网址 http://quotes.money.163.com/hs/service/marketradar_ajax.php?host=http%3A%2F%2Fquotes.mon ...

  8. 用Java爬虫爬取凤凰财经提供的沪深A股所有股票代号名称

    要爬取的凤凰财经网址:http://app.finance.ifeng.com/list/stock.php?t=hs 本作主要采用的技术是jsoup,相关介绍网页:https://www.jians ...

  9. docker打包项目

    nginx镜像制作实战 docker容器的主业 docker理念里,容器启动时,应当为它指定主业是什么,如nginx容器主业就是nginx代理服务,tomcat容器就是web服务等等 1.容器创建时, ...

  10. 关于Vue-Router的那些事儿

    Vue-Router Vu-router是Vue.js的官方路由管理器,方便于构建页面,在我们的使用过程中,一般是在router的index.js文件中配置对应的组件和对应的路径 主要的功能 嵌套路由 ...