转载: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. 【Android】Scrollview返回顶部,快速返回顶部的功能实现,详解代码。

    作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现 ...

  2. 【Unity C#编程】自定义数据

    译林军 灰魅|2014-03-04 10:52|10589次浏览|Unity(315)移动应用(31)技术开发(16)0 在这篇Unity C#的文章中,你将会创建一个简单的数据结构,然后写下它的属性 ...

  3. Lct 动态链接树

    通过树链剖分能了解轻重边 Acdreamer 的博客 http://blog.csdn.net/acdreamers/article/details/10591443 然后看杨哲大大的论文,能了解轻重 ...

  4. Google Code Jam 2020 Round1B Join the Ranks

    题意 给你一个形如\(1,2,\cdots,R,1,2,\cdots,R,1\cdots\)的序列,共重复\(C\)次.你每次可以选择一个区间\([L,R]\)将其平移到序列首部,最终使得序列具有\( ...

  5. 为什么 char 数组比 String 更适合存储密码?

    推荐阅读:5 个刁钻的 String 面试题! 另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员可以正确回答这个问题. 这是一个真正艰难的核心 Java 面试问题, ...

  6. JVM学习第三天(JVM的执行子系统)之类加载机制补充

    昨晚没看完,今天继续 系统的类加载器 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间.这句话可以表达得更通俗一些: ...

  7. 杭电oj2093题,Java版

    杭电2093题,Java版 虽然不难但很麻烦. import java.util.ArrayList; import java.util.Collections; import java.util.L ...

  8. String.format与搭配转化符的使用

    String的format语法搭配转化符,在格式化输出方面效果特别好,值得掌握. 例程: System.out.println("----C1---|----C2---|----C3---| ...

  9. 20190923-08Linux压缩和解压类 000 016

    gzip/gunzip 压缩 1.基本语法 gzip 文件 (功能描述:压缩文件,只能将文件压缩为*.gz文件) gunzip 文件.gz (功能描述:解压缩文件命令) 2.经验技巧 (1)只能压缩文 ...

  10. 再深入一点|binlog和relay-log到底长啥样?

    上一篇mysql面试的文章之后收到不少朋友的意见,希望深入讲讲复制.日志的格式这些,今天,我们就来深挖一下mysql的复制机制到底有哪一些,以及binlog和relay-log的结构到底是什么样子的. ...