举例说明自定义C++异常处理的实例
作者:_QING_FENG 发布时间:2022-10-25 13:45:27
举例说明自定义C++异常处理的实例
例1:自定义一个继承自excepton的异常类myException
C++标准中,定义在<stdexcept>中的任何异常类都派生自exception Class,本例也只是简单地由exception继承,在try段抛出一个异常并捕捉。代码如下:
/*++ test.cpp
version:1.0
decript:define a exception class named myException
derived from base class exception
which is declared in <exception>
created:2011-08-14
author: btwsmile
--*/
#include<exception>
#include<iostream>
using namespace std;
//customized exception class 'myException'
class myException:public exception
{
public:
myException():exception("ERROR! Don't divide a number by integer zero.\n")
{
}
};
//entry of the application
int main()
{
int x=100,y=0;
try
{
if(y==0) throw myException();
else cout<<x/y;
}
catch(myException& me)
{
cout<<me.what();
}
system("pause");
return 0;
}
结果如下:
ERROR! Don't divide a number by integer zero.
请按任意键继续. . .
显然,异常被捕捉到了。此处需要说明的是,VC对异常处理类exception进行了扩展,本例之所以能够使用exception("ERROR!....")的初始化方法正出于这样的原因,C++标准是不允许这样做的。
与此同时,VC又没有遵循标准,有力地支持terminate和unexpected,它只保留了语法,却在编译运行时不提供支持。为了结合terminate和unexpected更加深入了解C++的异常处理,下面的例子采用Dev cpp IDE实现。
例2:依照C++标准实现自定义异常类myException并将throw语句封装到函数check()中涉及到的更改正如标题所述,(1)重写基类的what()函数,返回错误信息;(2)将throw myException()封装到check()函数中;(3)允许check()函数抛出myException类型的异常。代码如下:
/*++ test.cpp
version:1.1
decript:define a exception class named myException
according to C++ standard,
derived from base class exception
which is declared in <exception>
!also,encapusulate throw into a function
created:2011-08-14
author: btwsmile
--*/
#include<exception>
#include<iostream>
using namespace std;
//customized exception class 'myException'
class myException:public exception
{
public:
const char* what()const throw()//#1
{
return "ERROR! Don't divide a number by integer zero.\n";
}
};
void check(int y) throw(myException)//#2
{
if(y==0) throw myException();
}
//entry of the application
int main()
{
int x=100,y=0;
try
{
check(y);
cout<<x/y;
}
catch(myException& me)
{
cout<<me.what();
}
system("pause");
return 0;
}
结果与例1完全相同。需说明的是,紧跟check()后的throw列表表明允许该函数抛出的异常类型。这里不得不产生疑问,如果抛出了一个不被允许的异常类型将怎样?
例3:抛出unexpected异常
check函数体之后的throw列表,规定了允许抛出的异常类型,一旦违背,就将触发unexpected。可以把unexpected看作系统自动调用的CALLBACK函数,不同的是,也可以手工触发它的执行。本例的情况属于前者。代码如下:
/*++ test.cpp
version:1.3
decript:define an unexpected excption handler,
set it by using set_unexpected,
modify the throw list of function check
created:2011-08-14
author: btwsmile
--*/
#include<exception>
#include<iostream>
using namespace std;
//customized exception class 'myException'
class myException:public exception
{
public:
const char* what()const throw()
{
return "ERROR! Don't divide a number by integer zero.\n";
}
};
void check(int y) throw()//#1 only int-type exception is permitted
{
if(y==0) throw myException();
}
void myUnexpected()
{
cout<<"Unexpected exception caught!\n";
system("pause");
exit(-1);
}
//entry of the application
int main()
{
unexpected_handler oldHandler=set_unexpected(myUnexpected);
int x=100,y=0;
try
{
check(y);
cout<<x/y;
}
catch(myException& me)
{
cout<<me.what();
}
system("pause");
return 0;
}
结果如下:
Unexpected exception caught!
请按任意键继续. . .
check函数的throw列表为空,即不允许抛出任何类型的异常,然而实际上当异常发生时,系统不能等闲视之,它将调用unexpected处理方法。所以,限定一个函数throw列表为空是值得程序员警醒的事,需要特别留意。如果将#1处的代码修改为throw(int)等也能得到相同的结果。所谓unexpected异常,说白了就是函数体允许抛出异常类型范围之外的异常。如果check函数后面根本没有throw,则表示函数任何类型的异常都被允许。
例4:抛出函数体允许的异常,但没被捕捉到的情况
思考这样一个问题,如果函数check的throw列表中有异常类型myException,而且在y==0时,它的确抛出myException类型的异常,但是没有被catch到,这时会发生什么?
在正式回答这个问题之前,先讨论“没被catch到”的意思。比如,修改例3的代码如下:(##为修改之处)
/*++ test.cpp
version:1.4.1
decript:
how to understand "exception not caucht"?
created:2011-08-14
author: btwsmile
--*/
#include<exception>
#include<iostream>
using namespace std;
//customized exception class 'myException'
class myException:public exception
{
public:
const char* what()const throw()
{
return "ERROR! Don't divide a number by integer zero.\n";
}
};
void check(int y) //any type of exception is permitted
{
if(y==0) throw myException();
}
void myUnexpected()
{
cout<<"Unexpected exception caught!\n";
system("pause");
exit(-1);
}
//entry of the application
int main()
{
unexpected_handler oldHandler=set_unexpected(myUnexpected);
int x=100,y=0;
try
{
check(y);
cout<<x/y;
}
catch(int &e) //##1 no catch sentence matches the throw type
{
cout<<e<<endl;
}
/* ##2 if add this part, any type which's not handler before will
be caught
catch(...)
{
cout<<"Unkown exception caught!\n";
}
*/
system("pause");
return 0;
}
编译运行,程序将会出错,因为check函数抛出的myException异常没有被处理。在缺省情况下,一旦出现抛出异常没被处理的问题,系统将自动调用abort()函数,终止程序允许,在控制台将会看到这样的提示:
This application has requested the Runtime to terminate it in an unusual way.Please contact the
application's support team for more information.
不过可以增加##2部分的代码,catch(...)表示捕捉任何类型的异常。
注意:check函数不被允许的异常类型并不会进入到catch语句的判断中来,因此catch(...)对unexpected exception没有作用。
仍然考虑没有##2部分的情况。正如前面所述,系统将自动调用abort()函数终止程序。实际上,它触发的是terminate,类似于unexpected,仍然可以自定义terminate的处理方法。甚至terminate语法上跟unexpected都十分近似。修改代码为:
/*++ test.cpp
version:1.4.2
decript:
how to understand "exception not caucht"?
created:2011-08-14
author: btwsmile
--*/
#include<exception>
#include<iostream>
using namespace std;
//customized exception class 'myException'
class myException:public exception
{
public:
const char* what()const throw()
{
return "ERROR! Don't divide a number by integer zero.\n";
}
};
void check(int y) //any type of exception is permitted
{
if(y==0) throw myException();
}
void myUnexpected()
{
cout<<"Unexpected exception caught!\n";
system("pause");
exit(-1);
}
void myTerminate() //##1 set it be the terminate handler
{
cout<<"Unhandler exception!\n";
system("pause");
exit(-1);
}
//entry of the application
int main()
{
unexpected_handler oldHandler=set_unexpected(myUnexpected);
terminate_handler preHandler=set_terminate(myTerminate);
int x=100,y=0;
try
{
check(y);
cout<<x/y;
}
catch(int &e) //no catch sentence matches the throw type
{
cout<<e<<endl;
}
system("pause");
return 0;
}
结果如下:
Unhandler exception!
请按任意键继续. . .
结论:C++为异常处理提供了友好的支持。
用户可以自定义异常类型,异常类型并不受到限制,可以是内建数据类型如int,double等,也可以是自定义的类,也可以从C++某个异常类继承下来。例1采用了派生自exception的方法。
除此之外,在定义函数时,可以显式指定函数体抛出的异常类型。隐式情况下,缺省允许函数抛出任何类型的异常。有可以增加throw语句,对异常类型加以限制。特别的是,throw()表示不允许函数抛出任何类型的异常。如果违反了throw列表规定的异常类型,系统将调用unexpected hanlder进行处理,可以自定义unexpected异常处理方法。例2和例3对它们进行了说明。
如果对于函数体throw列表合法的异常被抛出,但是却没有被程序捕捉处理,系统将调用terminate handler进行处理。缺省情况下,只是简单调用abort()函数终止程序,同样可以自定义terminate处理方法。例4对它进行了说明。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
来源:http://blog.csdn.net/q_l_s/article/details/24722909


猜你喜欢
- 实现闹钟运行的效果如下: 通知栏的运行后效果图如下:布局文件(activity_main.xml)<?xml version
- 五十七、只针对异常情况才使用异常: 不知道你否则遇见过下面的代码: &
- 本文实例为大家分享了Android实现3D云标签效果的具体代码,供大家参考,具体内容如下一、自定义Viewpublic class TagC
- 两种基本的输入方式1.使用Scanner类需要java.util包构造Scanner类的对象,附属于标准输入流System.in,之后通过其
- 概述对于Web开发者,MVC模型是大家再熟悉不过的了,SpringMVC中,满足条件的请求进入到负责请求分发的DispatcherServl
- Android 无障碍的全局悬浮窗可以在屏幕上添加 UI 供用户进行快捷操作,可以展示在所有应用程序之上长期展示。另一方面,在一些自动化场景
- 前言:本文介绍Java中数组转为List三种情况的优劣对比,以及应用场景的对比,以及程序员常犯的类型转换错误原因解析。一.最常见方式(未必最
- 1. interrupt知识点 以下总结基于JDK8本文不会完整说明interrupt,只会罗列一些比较重要的点。完整了解Thre
- 一. 接口文档概述swagger是当下比较流行的实时接口文文档生成工具。接口文档是当前前后端分离项目中必不可少的工具,在前后端开发之前,后端
- 动态获取对象的性能值,这个在开发过程中经常会遇到,这里我们探讨一下何如高性能的获取属性值。为了对比测试,我们定义一个类Peoplepubli
- 本文实例讲述了java实现List中对象排序的方法。分享给大家供大家参考,具体如下:package com.test; import jav
- 1.介绍当系统准备为用户提供一系列相关对象,又不想让用户代码和这些对象形成耦合时,就可以使用抽象工厂模式。2.如何实现1)抽象产品--Car
- 亲爱的读者,在这篇文章中,我提供了一些c#编程的最佳实践。你是否在用户输入验证中使用异常处理机制?如果是,那么你就是那个把你的项目执行速度降
- 1.算法效率算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。时间复杂度主要衡
- 🍅1.注解JUnit提供了非常强大的注解功能,通过@Test注解修饰到方法上,该方法就变为了一个测试方法,执行当前类时,会自动的执行该类下所
- 在Android中,使用摄像头拍照一般有两种方法, 一种是调用系统自带的Camera,另一种是自己写一个摄像的界面。
- (一)打包与运行SpringBoot项目快速启动(Linux版)基于Linux (CenteroS7)安装JDK,且版本不低于打包时使用的J
- 本文通过两个方法:(1)计算总的页数。 (2)查询指定页数据,实现简单的分页效果。思路:首先得在 DAO 对象中提供分页查询的方法,在控制层
- 在安卓开发中,经常会使用到一些动画,那么在开发中,如何使用这些动画呢?帧动画:不是针对View做出一些形状上的变化,而是用于播放一张张的图片
- 前言当线程池的线程阻塞时,线程池会创建额外的线程,而创建、销毁和调度线程所需要相当昂贵的内存资源,另外,很多的开发人员看见自己程序的线程没有