转载: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. Mac系统下php.ini的位置

    http://blog.csdn.net/meegomeego/article/details/25704645 /private/etc/php.ini /usr/local/etc/php/5.5 ...

  2. MaterialPropertyBlock

    在unity中,有这样一种情形,有许多的物体,都使用了相同的材质球,但是呢,具体的细节又有些微的不同,如果想要些微的改变每一个 网格的颜色,改变 渲染状态是不行的. 这时,就可以使用MaterialP ...

  3. 设计模式(多个if的处理)

    使用场景 如果在代码中出现大量if判断,再执行一些比较复杂的业务操作,类似于以下情况. @Test void test() { String str = "A"; if (str. ...

  4. 剑指 Offer 55 - II. 平衡二叉树

    题目描述 输入一棵二叉树的根节点,判断该树是不是平衡二叉树.如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树. 示例1: 给定二叉树 [3,9,20,null,null,1 ...

  5. centos7安装jdk11

    我下载的网址是http://jdk.java.net/11/ 找安装包的事就说到这里了.我是因为公司用的jdk8,但是,我给个人研究东西的时候,目前定的版本是jdk11 .另外,现在基本全线转到了op ...

  6. 用Python写一个向数据库填充数据的小工具

    一. 背景 公司又要做一个新项目,是一个合作型项目,我们公司出web展示服务,合作伙伴线下提供展示数据. 而且本次项目是数据统计展示为主要功能,并没有研发对应的数据接入接口,所有展示数据源均来自数据库 ...

  7. git 修改已提交了的备注信息的方法

    git 修改已提交了的备注信息的方法: 1.当我们已通过 git commit -m '已提交的最新的备注' 命令将代码提交到了缓存区,或者进一步执行了 git push origin master ...

  8. 中间件、蓝图、g对象

    中间件 ''' flask中一旦请求到来,要执行app()--->>>执行的是app.__call__,整个flask的入口 ''' from flask import Flask ...

  9. 在浏览器输入 URL 回车之后发生了什么(超详细版)

    前言 这个问题已经是老生常谈了,更是经常被作为面试的压轴题出现,网上也有很多文章,但最近闲的无聊,然后就自己做了一篇笔记,感觉比之前理解更透彻了. 这篇笔记是我这两天看了数十篇文章总结出来的,所以相对 ...

  10. Linux安装软件总结

    1.安装jdk1.8 1.首先去官网下载jdk https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133 ...