1)异常是一种程序控制机制,与函数机制独立和互补
函数是一种以栈结构展开的上下函数衔接的程序控制系统,异常是另一种控制结构,它依附于栈结构,却可以同时设置多个异常类型作为网捕条件,从而以类型匹配在栈机制中跳跃回馈.
2) 异常设计目的:
栈机制是一种高度节律性控制机制,面向对象编程却要求对象之间有方向、有目的的控制传动,从一开始,异常就是冲着改变程序控制结构,以适应面向对象程序更有效地工作这个主题,而不是仅为了进行错误处理。
异常设计出来之后,却发现在错误处理方面获得了最大的好处。
1.异常处理的基本思想
1.1传统的错误处理机制
通过函数返回值来处理错误。
1.2异常的错误处理机制
1)C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层调用者可以再适当的位置设计对不同类型异常的处理。
2)异常是专门针对抽象编程中的一系列错误处理的,C++中不能借助函数机制,因为栈结构的本质是先进后出,依次访问,无法进行跳跃,但错误处理的特征却是遇到错误信息就想要转到若干级之上进行重新尝试,如图
3)异常超脱于函数机制,决定了其对函数的跨越式回跳。
4)异常跨越函数
#include
using namespace std;
void divide(int x,int y)
{
if (y == 0)
{
//出现了非法的算术
cout<<"发现y==0"<
2.C++异常处理的实现
1)若有异常则通过throw操作创建一个异常对象并抛掷。
2)将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句,然后执行try块内的保护段。
3)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去。
4)catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛掷异常)。
5)如果匹配的处理器未找到,则运行函数terminate将被自动调用,其缺省功
能是调用abort终止程序。
6)处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔
2.1栈解旋(unwinding)
异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反。这一过程称为栈的解旋(unwinding)。
#include
using namespace std;
class Test
{
public:
Test(int a,int b){
this->a = a;
this->b = b;
cout<<"Test(int ,int)...."<
2.2异常接口声明
1)为了加强程序的可读性,可以在函数声明中列出可能抛出的所有异常类型,例如:
void func() throw (A, B, C , D);
//这个函数func()能够且只能抛出类型A B C D及其子类型的异常。
2)如果在函数声明中没有包含异常接口声明,则次函数可以抛掷任何类型的异常,例如:
void func();
3)一个不抛掷任何类型异常的函数可以声明为:
void func() throw();
4)如果一个函数抛出了它的异常接口声明所不允许抛出的异常,unexpected函数会被调用,该函数默认行为调用terminate函数中止程序。
void func2()//什么异常都可以
{
}
void func() throw()//代表此函数不会抛出异常
{
throw 1;//想抛它也不拦你,只报警告
}
void divide(int x,int y) throw(char)//报警告了,因为抛出一个int型
{
Test t1(1,2);
Test t2(10,20);
if (y == 0)
{
throw x;
}
cout<<"x / y = "<< x / y <
2.3异常类型和异常变量的生命周期
1)throw的异常是有类型的,可以使,数字、字符串、类对象。
2)throw的异常是有类型的,catch严格按照类型进行匹配。
3)注意异常对象的内存模型。
//异常类型
class BadDstAddrType{};
class BadSrcAddrType{};
class BadProcessAddrType{
public:
BadProcessAddrType(){
cout<<"BadProcessAddrType()..."<
3.标准程序库异常
每个类所在的头文件在图下方标识出来.
标准异常类的成员:
① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、赋值操作符重载。
② logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述;
③ 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息。
#include
#include
#include
using namespace std;
//自定义的MyException的类,也加入标准的异常库
class MyException:public exception
{
public:
MyException(char *str){
this->m_s = str;
}
virtual const char * what() const{//what()必须重写,自己去看!
cout<<"MyException 的异常"<m_s;
}
private:
char *m_s;
}
class Teacher
{
public:
Teacher(string name,int id){
this->name = name;
if (id > 100)
{
string str = "id超出范围";
throw out_of_range(str);
}
this->id = id;
}
private:
int id;
string name;
};
int main(void)
{
try{
Teacher t1("zhang3",10001);
}
catch(exception &e){//exception所有都能接!
cout<