C++异常的处理机制

1、异常的概述

常见的异常:除0溢出,数组下标越界,所要读取的文件不存在,空指针,内存不足等等。

c++的异常一旦抛出 如果不捕获 该异常 程序直接退出

1.1、C语言通过返回值 来判断 第一:容易忽略 第二:容易和正常的结果混淆

int myDiv(int a,int b)
{
    if(b == 0)
        return -1;//-1表示失败
    return a/b;
}

void test01()
{
    int ret = myDiv(10,-10);
    if(ret == -1)
    {
        cout<<"程序异常了"<<endl;
    }
    else
    {
        cout<<"程序正常"<<endl;
    }
}

运行结果:
在这里插入图片描述

1.2、c++抛出异常 并捕获

c++的异常一旦抛出 如果不捕获 该异常 程序直接退出

抛出异常:throw

捕获异常:try…catch

int myDiv01(int a,int b)
{
    if(b==0)
        throw 0;//抛出异常

    return a/b;
}
void test02()
{
    try{
        int ret = myDiv01(10,0);
        cout<<"ret = "<<ret<<endl;
    }
#if 1
    catch(int e)//只捕获 抛出是int类型的异常
    {
        cout<<"捕获到int类型异常 e = "<<e<<endl;
    }
#endif
    catch(float e)//只捕获 抛出是float类型的异常
    {
        cout<<"捕获到float类型异常 e = "<<e<<endl;
    }
    catch(char e)//只捕获 抛出是char类型的异常
    {
        cout<<"捕获到char类型异常 e = "<<e<<endl;
    }
#if 0
    catch(...)
    {
        cout<<"捕获到其他异常"<<endl;
    }
#endif

    cout<<"程序做其他事情"<<endl;
}

运行结果:
在这里插入图片描述

2、栈解旋(unwinding)

异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反,这一过程称为栈的解旋(unwinding).

void test03()
{
    try{

        Person ob1("00_德玛");
        Person ob2("01_小炮");
        Person ob3("02_小法");
        Person ob4("03_提莫");

        throw 10;
    }
    catch(int)
    {
        cout<<"捕获到int异常"<<endl;
    }
    cout<<"其他工作"<<endl;
}

运行结果:
在这里插入图片描述

3、异常的接口声明

throw(int,char,char*) 只抛出intcharchar *异常
void testFunc01()
{
    //函数内部可以抛出任何异常
    //throw 10;
    //throw 4.3f;
    //throw 'a';
    //throw "hehe";
    string ob="heihie";
    throw ob;
}

//只能抛出int char 异常
void testFunc02() throw(int,char)
{
    throw 3.14f;
}

//函数 不抛出任何异常
void testFunc03()throw()
{
    throw 10;//外部捕获 不到
}

void test04()
{
    try{
        testFunc03();
    }
    catch(int e)//只捕获 抛出是int类型的异常
    {
        cout<<"捕获到int类型异常 e = "<<e<<endl;
    }
    catch(float e)//只捕获 抛出是float类型的异常
    {
        cout<<"捕获到float类型异常 e = "<<e<<endl;
    }
    catch(char e)//只捕获 抛出是char类型的异常
    {
        cout<<"捕获到char类型异常 e = "<<e<<endl;
    }
    catch(char const *e)//只捕获 抛出是char *类型的异常
    {
        cout<<"捕获到char const *类型异常 e = "<<e<<endl;
    }
    catch(string e)
    {
        cout<<"捕获到string类型异常 e = "<<e<<endl;
    }
}

4、异常的生命周期 的三种情况

4.1、以普通变量形式捕获

class MyException
{
public:
    MyException()
    {
        cout << "异常变量构造" << endl;
    };
    MyException(const MyException & e)
    {
        cout << "拷贝构造" << endl;
    }
    ~MyException()
    {
        cout << "异常变量析构" << endl;
    }
};
void text() //抛出异常
{
    MyException ob;
    throw ob;
}
void test01()
{
    try {
        text();
    } catch (MyException e) {
        cout << "捕获到MyException异常" <<endl;
    }
}

运行结果:
在这里插入图片描述

4.2、以指针形式捕获

void test02()
{
    try {
        //text();
        throw new MyException;
    } catch (MyException *e) {
        cout << "捕获到MyException *异常" <<endl;
        delete e;   //必须记得释放e
    }
}

运行结果:
在这里插入图片描述

4.3、以引用形式捕获(推荐使用)

void test03()
{
    try {
        //text();
        throw MyException();
    } catch (MyException &e) {
        cout << "捕获到MyException &异常" <<endl;
    }
}

在这里插入图片描述

5、标准异常

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

案例

class Person2
{
private:
    int age;
public:
    Person2(int age)
    {
        if(age<0 || age >150)
            throw out_of_range("age无效");
        this->age =age;
    }
};
void test06()
{
    try{
        Person2 ob(200);
    }
    catch(exception &e)
    {
        cout<<"捕获到异常"<<e.what()<<endl;
        //e.what() : age无效
    }
}

6、异常的多态使用

在这里插入图片描述

发布了78 篇原创文章 · 获赞 45 · 访问量 9271

猜你喜欢

转载自blog.csdn.net/weixin_43288201/article/details/105169730