转载: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. IO优化

    Linux性能优化之CPU.内存.IO优化 https://blog.csdn.net/zyc88888/article/details/79027944 iOS的I/O操作 https://www. ...

  2. P1020 导弹拦截(nlogn求最长不下降子序列)

    题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...

  3. [BUUOJ记录] [BJDCTF 2nd]old-hack & Schrödinger & elementmaster

    三道比较简单的的题放一起一写,old-hack是ThinkPHP框架的一个nday,Schrödinger和elementmaster没啥考点,就是脑洞 一.old-hack 进入题目没发现什么Hi ...

  4. Activiti7 zip部署,查询及其删除

    zip部署 package com.itheima.activiti; import org.activiti.engine.ProcessEngine; import org.activiti.en ...

  5. Agumaster 增加雪球网爬虫

  6. JVM中的对象

    虚拟机中的对象 对象的分配 虚拟机遇到一条new指令时:根据new的参数是否能在常量池中定位到一个类的符号引用,如果没有,说明还未定义该类,抛出ClassNotFoundException: 1)检查 ...

  7. leetcode刷题-49字母异位词分组

    题目 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 思路 由于异位词由相同字母构成,所以可以用一个顺序的字符串作为这些字母异位词的标志,由此可以想到字典的方法 ...

  8. 转发请求RequestDispatcher()方法用于与页面的交互

    jsp1代码 <form action="HelloServlet" > 账号: <input type="text" name=" ...

  9. synchronized的实现原理——锁膨胀过程

    @ 目录 前言 正文 偏向锁 轻量锁 批量重偏向 批量撤销 重量锁 总结 前言 上一篇分析了优化后的synchronized在不同场景下对象头中的表现形式,还记得那个结论吗?当一个线程第一次获取锁后再 ...

  10. 架构设计 | 基于Seata中间件,微服务模式下事务管理

    源码地址:GitHub·点这里 || GitEE·点这里 一.Seata简介 1.Seata组件 Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata将为用 ...