zoukankan      html  css  js  c++  java
  • C++中的异常

    一,异常的推演

    1.函数与异常

      平时我们在函数中出现异常情况时通常通过return终止函数并返回一个值,然后在函数上层来获取值并判断是什么异常情况。因为函数是栈结构的,所以return的时候是通过栈结构逐步往上的,不能够跨函数直接抛出,不方便。所以C++推出了异常机制,通过异常机制我们可以轻松的捕获要出现的异常。

    2.C++中异常的基本演示

    复制代码
    # include<iostream>
    using namespace std;
    
    /* 定义求商函数,如果除数为0,抛出double类型异常 */
    double div(double d1, double d2)
    {
        if (d2 == 0)
        {
            throw d2;
        }
        return d1 / d2;
    }
    
    int main()
    {
        /* try...catch语句来捕获异常 */
        try
        {
            double result = div(1.02, 0.0);
        }
        catch (double e)
        {
            /* C++中的异常严格要求类型匹配,即抛出什么的异常就catch什么类型的异常 */
            cout << e << "不能作除数" << endl;
        }
        catch (...)
        {
            cout << "未知异常" << endl;
        }
    
        return 0;
    }
    复制代码

     3.C++中异常的总结

    • 异常的捕捉严格匹配数据类型,不支持类型自动转换,throw的是int类型则catch的必须是int类型否则不会匹配。
    • 一般我们在异常最后加入catch(...)这样能够捕获任意异常。

    二,自定义异常类

    1.异常类

      按照面向对象的思维,我们的异常也应该是一个对象,所以在抛出异常的时候,我们通常自定义一个异常类,然后把异常信息放入异常类中,然后在捕捉到异常对象的时候,再调用对象的方法,打印出异常的信息。

    2.异常类代码演示

    复制代码
    # define _CRT_SECURE_NO_WARNINGS
    # include<iostream>
    using namespace std;
    
    /* 自定义异常类 */
    class MyException
    {
    private:
        char * content;
    public:
        /* 异常类构造函数 */
        MyException(const char * content)
        {
            this->content = new char[strlen(content) + 1];
            strcpy(this->content, content);
            cout << "异常类有参构造函数执行" << endl;
        }
        /* 异常类拷贝构造函数 */
        MyException(const MyException& me)
        {
            this->content = new char[strlen(me.content) + 1];
            strcpy(this->content, me.content);
            cout << "异常类拷贝构造函数执行" << endl;
        }
        /* 异常类析构函数 */
        ~MyException()
        {
            if (this->content != NULL)
            {
                delete[] this->content;
                this->content = NULL;
            }
            cout << "异常类的析构函数执行" << endl;
        }
        /* 异常类抛出异常信息 */
        void toString()
        {
            cout << this->content << endl;
        }
    };
    
    /* 定义测试异常的函数 */
    double divide(double d1, double d2)
    {
        if (d2 == 0)
        {
            throw MyException("除数不能为0");
            //throw new MyException("除数不能为0");
        }
        return d1 / d2;
    }
    
    int main()
    {
        try
        {
            double result = divide(1, 0);
            cout << "result = " << result << endl;
        }
        catch (MyException e)
        {
            // catch的异常是元素类型,执行的是拷贝构造函数,存在两个异常对象,释放两个异常对象,不合理
            e.toString();
        }
        catch (MyException * e)
        {
            // catch的异常是指针类型,必须我们手动调用delete方法才能调用析构函数,不合理
            e->toString();
            delete e;
        }
        catch (MyException& e)
        {
            // catch的是引用类型,是原先抛出的对象,会自动执行析构函数,我们使用引用来接收抛出的异常对象
            e.toString();
        }
        catch (...)
        {
            cout << "未知异常" << endl;
        }
    
        return 0;
    }
    复制代码

    3.自定义异常类总结

    • 抛出异常对象通常用引用的方式来catch这个对象,如果是元素catch异常对象则会执行拷贝构造函数,创建两个重复异常对象并释放两次对象,所以说不合理。如果catch的是指针类型,不会自动调用该对象的析构函数必须我们手动delete,也不符合自动调用的逻辑,所以使用引用的方式来catch异常对象。

    三,标准异常类

    1.标准异常类

      C++中提供了标准的异常类,需要# include<exception>,标准异常类为exception,该类有个what函数,可以打印异常对象的异常信息。该what函数是虚函数,我们需要继承exception类并重写该what函数,在捕捉异常的时候,我们用父类的引用来接收自定义的标准异常类的子类对象(类型兼容性原则),然后打印该异常信息即可。

    2.标准异常类演示

    复制代码
    # include<iostream>
    # include<exception>
    using namespace std;
    
    /* 继承自标准异常类 */
    class DivException :public exception
    {
    private:
        const char * ptr;
    public:
        /* 构造函数接收异常信息 */
        DivException(const char * ptr)
        {
            this->ptr = ptr;
        }
        /* 重写what函数 */ 
        virtual char const * what() const
        {
            cout << this->ptr << endl;
            return ptr;
        }
    };
    /* 测试异常函数 */
    int divi(int a, int b)
    {
        if (b == 0)
        {
            throw DivException("除数不能为0");
        }
        return a / b;
    }
    
    int main()
    {
        try
        {
            divi(10, 0);
        }
        catch (exception& e)
        {
            /* 使用exception引用接收自定义的子类对象 */
            e.what();
        }
        catch (...)
        {
            cout << "未知异常" << endl;
        }
    
        return 0;
    }
    复制代码
  • 相关阅读:
    Maximum Flow Exhaustion of Paths Algorithm
    ubuntu下安装java环境
    visualbox使用(二)
    vxworks一个超级奇怪的错误(parse error before `char')
    February 4th, 2018 Week 6th Sunday
    February 3rd, 2018 Week 5th Saturday
    February 2nd, 2018 Week 5th Friday
    February 1st, 2018 Week 5th Thursday
    January 31st, 2018 Week 05th Wednesday
    January 30th, 2018 Week 05th Tuesday
  • 原文地址:https://www.cnblogs.com/aeexiaoqiang/p/6526218.html
Copyright © 2011-2022 走看看