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、異常的多態使用

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章