C++ 异常处理(基础篇)
来源:互联网 发布:网红拍照软件 编辑:程序博客网 时间:2024/05/22 01:58
异常处理:
不同的编译器处理异常时的表现不同,有的崩溃,有的其它形式
希望编写所有编译器上都以相同的受控方式运行的代码
方式1:调用abort()、exit()
(在程序出现异常时,将退出程序)
方式2:返回错误代码
例如:程序正常运行时返回true,异常时返回false,或设置一个全局变量,在程序异常时,设置为一个特殊的值
(在程序出现异常时,不退出程序,能继续执行)
方式3:异常机制
(在程序出现异常时,能给出匹配的异常类型,并继续执行)
1>异常处理的组成部分
throw “... ”:引发异常,其后的值指出了异常的特征
catch ():捕获异常,括号中指出了异常处理程序要响应的异常类型
try { } :指出需要注意大括号的中代码,引发的异常,可能引发异常的函数,必须放在try块内,否则将无法处理异常
2>异常处理的执行次序
throw语句终止函数执行,导致程序沿函数调用序列后退,直到找到包含try块的函数,
找到后,匹配try块后面的catch块类型,匹配成功后,执行catch块中的语句
3>缺失情况
如果引发了异常,而没有try块或没有匹配的处理程序时,在默认情况下,程序将调用abort()函数【这种行为可以修改】
4>catch()块中的异常类型
异常类型可以是字符串、其他C++类型,通常为类类型
例子:bad_hmean异常类
class bad_hmean
{
private:
double v1;
double v2;
public:
bad_hmean(int a=0,int b=0):v1(a),v2(b){};
void mesg();
}
inline void bad_hmean::mesg()
{
std::cout<<"hmean("<<v1<<", "<<v2<<"):"<<"invalid arguments: a=-b\n‘;
}
5>异常规范
异常规范由throw和异常类型列表组成,加在函数定义的后面。对于引发多种异常的函数,可提供一个由逗号分隔的异常类型列表组成
例如:double multi(double a,double b) throw(const char *s,double);
函数定义应包含原型中的信息:
double hmean(double a,double b) throw(bad_hmean)
{
if(a==-b)
throw bad_hmean(a,b);
else
return 2.0*a*b/(a+b);
}
如果异常规范中的括号内为空,则表明该函数不会引发异常
double se(double x) throw();
6>堆栈解退
假设try块没有直接调用引发异常的函数,而是调用了对引发异常的函数进行调用的函数,则程序流程将从引发异常的函数跳到包含try块的处理程序的函数
函数正常返回:函数通常都返回到调用它的函数,一次类推,同时每个函数都在结束时释放其自动变量,自动变量是类对象则调用类的析构函数
函数由于出现异常(不是由于返回)而终止:则程序将会释放堆栈中的内存,但不会在释放堆栈的第一个返回地址后停止,而是继续释放堆栈,直到找到一个位于try块中的返回地址。随后,控制权将转到块尾的异常处理程序,而不是函数调用后面的第一条语句。这个过程就是堆栈解退。
函数返回仅仅处理该函数放在堆栈中的对象,而throw语句则处理try块和throw之间整个函数调用序列放在堆栈中的对象
7>异常规范补充。。。
例子:
try{
z=means(x,y);
}
catch(bad_hmean &bh){}
catch(bad_gmean &bg){}
double means(double a,double b) throw(bad_hmean,bad_gmean) //异常规范不仅要包含函数本身引发的异常,
{ //还应包含该函数调用的其它函数引发的异常,依次类推,means()调用了gmean(),因此它应宣称自己能传递gmean()引发的异常
try{
hm=hmean(a,b);
gm=gmean(a,b);
}
catch(bad_hmean &bh){...throw} //执行完会再跳到main()函数中的try块
}
8>throw-catch与return的区别
区别1:函数function()的return语句将控制权返回到调用function()的函数
throw-catch语句则将控制权向上返回到第一个包含能够捕获相应异常的try-catch组合
区别2:引发异常时,编译器将创建一个临时拷贝,即使异常规范和catch块中指定的是引用
例子:
try{
super();
}
catch(problem &p){} //p指向oop的拷贝而不是oop本身,super()执行完毕后,oop将消失
void super() throw(problem)
{problem oop;
throw oop;}
问题:既然throw将生成拷贝,为什么代码中使用引用呢?
答:基类的引用可以指向派生类对象,基类引用与任何派生类对象匹配
9>catch块排列顺序
引发的异常对象将被第一个与之匹配的catch块捕获,所以catch块的排列顺序应该与派生类的顺序相反
例子:
class bad1{};
class bad2: public bad1{};
class bad3: public bad2{};
void duper() throw(bad1)
{
if() throw bad1();
if() throw bad2();
if() throw bad3();
}
try{
duper();
}
catch(bad3 &b3) {}
catch(bad2 &b2) {}
catch(bad1 &b1) {} //基类与所有它的派生类匹配
10>补充
假设编写了一个调用另一个函数的函数,但不知道被调用的函数可能引发哪些异常,在这种情况下,使用省略号表示异常类型
catch(.....){}
- C++ 异常处理(基础篇)
- android基础篇------------java基础(8)(异常处理)
- python异常处理(基础)
- python异常处理(基础)
- java 基础(异常处理)
- python异常处理(基础)
- C异常处理(1)
- C异常处理(2)
- C++(2):异常处理
- 异常处理(二、C语言的异常处理)
- Object-C基础(10)——异常处理、反射、动态调用方法与内存回收
- java异常处理——基础篇
- java基础篇--07<java异常处理>
- C++ 异常处理基础(1)
- (C#基础)异常处理二三事
- java 基础:异常处理(六)
- JavaSE基础--(四)异常处理
- JavaSe基础(22)-- 异常与处理
- C# base和this
- POJ Genealogical tree(拓扑排序)
- oracle sql日期
- getOutputStream() has already been called for this response异常的原因和解决方法
- 编程之美 2013 全国挑战赛 资格赛 题目三 树上的三角形
- C++ 异常处理(基础篇)
- 电容充放电
- 二叉树的遍历(更新中)
- apache:2.2.17 php 5.3.5
- 应该被记住的8位Java人物
- Holmos自动化测试入门学习(一)-------打开/关闭浏览器&&页面常用方法举例
- Linux (ubuntu)下安装eclipse
- 【Oracle】-【show_space和show_space_asm】-执行存储过程show_space和show_space_asm报错
- android应用程序安装位置android:installLocation翻译