异常处理

异常

​ 异常处理允许用户以一种有序的方式管理运行是出现的错误。使用C++的异常处理,用户程序在错误发生时可自动调用一个错误处理程序。异常处理最主要的优点是自动转向错误处理代码,而以前在大程序中这些代码是由“手工”编制的。

​ 简单来说异常,是利用代码来代替程序员调试解决程序的出错

异常的优点

  1. 函数的返回值可以忽略,但异常不可忽略。如果程序出现异常,但是没有被捕获,程序就会终止,这多少会促使程序员开发出来的程序更加健壮。而如果没有使用C语言的error宏或者函数返回值,调试者都有可能忘记检查,从而没有对错误进行处理,结果造成程序莫名的终止或出现错误的结果。
  2. 整形返回值没有任何语义信息。而异常却包含语义信息,优势能从类名就能够体现出来。
  3. 整形返回值缺乏相关的上下文信息。异常作为一个雷,可以拥有自己的成员,这些成员就可以传递足够的信息。
  4. 异常处理可以在调用调剂。这是一个代码编写时的问题:假设在有多个函数的调用栈中出现了某个错误,使用整形返回码要求你再每一级函数中都要进行处理。而使用异常处理的栈展开机制,只需要在一出进行处理就可以了,不需要每级函数都处理。

基本语法

异常捕获是根据类型进行匹配的

int divide(int x,int y)
{
    if(y==0)
    {
        throw y;
    }
    return x/y;
}
void test()
{
    try//尝试捕获异常
    {
        divide(10,0);
    }
    catch(int e)//异常时根据类型进行匹配
    {
        cout<<"除数为"<<e<<"!"<<endl;
    }
}
  • 如果函数抛出异常,如果该函数没有处理异常,会抛到顶层函数,如果还没有会逐步抛出(跨函数),该层函数接下来的代码不会被执行。异常必须处理,而且是跨函数。

异常接口声明

  • 为了加强程序的可读性,可以在函数声明中列出可能抛出异常的所有类型,例如:void func();throw(A,B,C);这个函数func能够且只能抛出类型A,B,C及其子类型的异常。
  • 如果函数声明中没有包含异常接口声明,则此函数可以抛出任何类型的异常,例如void func()
  • 一个不抛任何类型异常的函数可以声明为:void func() throw()
  • 如果一个函数抛出了它的异常接口声明锁不允许抛出的异常,unexcepted函数会被调用,该函数默认行为调用terminate函数中断程序。

异常类型

可以定义捕获异常的类型:

//这个函数只能抛出int,float,char三种类型异常,抛出其他的就报错
void func() throw(int,float,char)
{
    throw "abc";
}
//不能抛出任何异常
void func2() throw()
{
    throw -1;
}
  • 若没有任何类型,则不能抛出异常
  • "…"代表,可以是任何异常
//......
catch(...)
{
    cout<<"未知类型异常!"<<endl;
}

异常对象

//异常对象,使用方法与普通数据类型相似
class MyException
{
public:
    MyException(char *str)
    {
        error = new char[strlen(str)+1];
        strcpy(error,str);
    }
    void what()
    {
        cout<<"未知异常!"<<endl;
    }
public:
    char *error;
};

//抛出一个对象
void fun3()
{
    throw MyException();
}

异常对象声明周期

  • 普通元素异常对象catch处理完之后析构,catch()如果接的是引用,不用调用拷贝构造,catch处理完之后析构
  • 指针的话在catch之前对象会析构掉,解决方法是throw new Exception,在catch里面delete

标准异常库

在这里插入图片描述
编写自己的异常类的规则:#include

  1. 自己的异常类要继承标准异常类。
  2. 重载父类的what函数和虚析构函数。
  • 为什么要编写自己的异常类?
    • 标准库中的异常时有限的
    • 在自己的异常类中,可以添加自己的信息。(标准库中的异常类值允许设置一个用来描述异常的字符串)
  • 如何编写自己的异常类?
    • 建议自己的异常类要继承标准异常类。因为c++中可以抛出任何类型的异常,所以我们的异常类可以不继承标准异常,但是这样可能会导致程序混乱,尤其是当我们多人协同开发时。
    • 当继承标准异常类时,应该重载父类的what函数和虚析构函数
    • 因为栈展开的过程中,要复制异常类型,那么要根据你再类中添加的成员考虑是否提供自己的复制构造函数。
class MyOutOfRange : public exception
{
public:
	MyOutOfRange(char *error)
    {
    	pError = new char[strlen(error)+1];
    	strcpy(pError,error);
    }
    ~MyOutOfRange()
    {
    	if(pError != NULL)
        {
        	delete[] pError;
        }
    }
    virtual const char *what() const
    {
    	return pError;
    }
public:
	char *pError;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值