2017年計(jì)算機(jī)二級(jí)C++實(shí)例編程:c++異常處理機(jī)制示例及講解

字號(hào):


    c++異常處理機(jī)制示例及講解
    下面的代碼直接貼到你的console工程中,可以運(yùn)行調(diào)試看看效果,并分析c++的異常機(jī)制。
    #include "stdafx.h"
    #include
    #include
    #include
    // 內(nèi)存泄露檢測(cè)機(jī)制
    #define _CRTDBG_MAP_ALLOC
    #ifdef _DEBUG
    #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
    #endif
    // 自定義異常類
    class MyExcepction
    {
    public:
    // 構(gòu)造函數(shù),參數(shù)為錯(cuò)誤代碼
    MyExcepction(int errorId)
    {
    // 輸出構(gòu)造函數(shù)被調(diào)用信息
    std::cout << "MyExcepction is called" << std::endl;
    m_errorId = errorId;
    }
    // 拷貝構(gòu)造函數(shù)
    MyExcepction( MyExcepction& myExp)
    {
    // 輸出拷貝構(gòu)造函數(shù)被調(diào)用信息
    std::cout << "copy construct is called" << std::endl;
    this->m_errorId = myExp.m_errorId;
    }
    ~MyExcepction()
    {
    // 輸出析構(gòu)函數(shù)被調(diào)用信息
    std::cout << "~MyExcepction is called" << std::endl;
    }
    // 獲取錯(cuò)誤碼
    int getErrorId()
    {
    return m_errorId;
    }
    private:
    // 錯(cuò)誤碼
    int m_errorId;
    };
    int main(int argc, char* argv[])
    {
    // 內(nèi)存泄露檢測(cè)機(jī)制
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    // 可以改變錯(cuò)誤碼,以便拋出不同的異常進(jìn)行測(cè)試
    int throwErrorCode = 110;
    std::cout << " input test code :" << std::endl;
    std::cin >> throwErrorCode;
    try
    {
    if ( throwErrorCode == 110)
    {
    MyExcepction myStru(110);
    // 拋出對(duì)象的地址 -> 由catch( MyExcepction* pMyExcepction) 捕獲
    // 這里該對(duì)象的地址拋出給catch語句,不會(huì)調(diào)用對(duì)象的拷貝構(gòu)造函數(shù)
    // 傳地址是提倡的做法,不會(huì)頻繁地調(diào)用該對(duì)象的構(gòu)造函數(shù)或拷貝構(gòu)造函數(shù)
    // catch語句執(zhí)行結(jié)束后,myStru會(huì)被析構(gòu)掉
    throw &myStru;
    }
    else if ( throwErrorCode == 119 )
    {
    MyExcepction myStru(119);
    // 拋出對(duì)象,這里會(huì)通過拷貝構(gòu)造函數(shù)創(chuàng)建一個(gè)臨時(shí)的對(duì)象傳出給catch
    // 由catch( MyExcepction myExcepction) 捕獲
    // 在catch語句中會(huì)再次調(diào)用通過拷貝構(gòu)造函數(shù)創(chuàng)建臨時(shí)對(duì)象復(fù)制這里傳過去的對(duì)象
    // throw結(jié)束后myStru會(huì)被析構(gòu)掉
    throw myStru;
    }
    else if ( throwErrorCode == 120 )
    {
    // 不提倡這樣的拋出方法
    // 這樣做的話,如果catch( MyExcepction* pMyExcepction)中不執(zhí)行delete操作則會(huì)發(fā)生內(nèi)存泄露
    // 由catch( MyExcepction* pMyExcepction) 捕獲
    MyExcepction * pMyStru = new MyExcepction(120);
    throw pMyStru;
    }
    else
    {
    // 直接創(chuàng)建新對(duì)象拋出
    // 相當(dāng)于創(chuàng)建了臨時(shí)的對(duì)象傳遞給了catch語句
    // 由catch接收時(shí)通過拷貝構(gòu)造函數(shù)再次創(chuàng)建臨時(shí)對(duì)象接收傳遞過去的對(duì)象
    // throw結(jié)束后兩次創(chuàng)建的臨時(shí)對(duì)象會(huì)被析構(gòu)掉
    throw MyExcepction(throwErrorCode);
    }
    }
    catch( MyExcepction* pMyExcepction)
    {
    // 輸出本語句被執(zhí)行信息
    std::cout << "執(zhí)行了 catch( MyExcepction* pMyExcepction) " << std::endl;
    // 輸出錯(cuò)誤信息
    std::cout << "error Code : " << pMyExcepction->getErrorId()<< std::endl;
    // 異常拋出的新對(duì)象并非創(chuàng)建在函數(shù)棧上,而是創(chuàng)建在專用的異常棧上,不需要進(jìn)行delete
    //delete pMyExcepction;
    }
    catch ( MyExcepction myExcepction)
    {
    // 輸出本語句被執(zhí)行信息
    std::cout << "執(zhí)行了 catch ( MyExcepction myExcepction) " << std::endl;
    // 輸出錯(cuò)誤信息
    std::cout << "error Code : " << myExcepction.getErrorId()<< std::endl;
    }
    catch(...)
    {
    // 輸出本語句被執(zhí)行信息
    std::cout << "執(zhí)行了 catch(...) " << std::endl;
    // 處理不了,重新拋出給上級(jí)
    throw ;
    }
    // 暫停
    int temp;
    std::cin >> temp;
    return 0;
    }