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;
}