西部数码主机 | 阿里云主机| 虚拟主机 | 服务器 | 返回乐道官网
当前位置: 主页 > 开发教程 > C/C++教程 >

C++中的异常

时间:2017-01-15 23:09来源:未知 作者:好模板 点击:
一,异常的推演 1.函数与异常 平时我们在函数中出现异常情况时通常通过return终止函数并返回一个值,然后在函数上层来获取值并判断是什么异常情况。因为函数是栈结构的,所以re

一,异常的推演

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;
}
(责任编辑:好模板)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
热点内容