c++異常處置機制示例及具體講授。本站提示廣大學習愛好者:(c++異常處置機制示例及具體講授)文章只能為提供參考,不一定能成為您想要的結果。以下是c++異常處置機制示例及具體講授正文
這兩天我寫了一個測試c++異常處置機制的例子,感到有很好的示范感化,在此貼出來,給c++異常處置的初學者入門。本文後附有c++異常的常識普及,有興致者也能夠看看。
上面的代碼直接貼到你的console工程中,可以運轉調試看看後果,並剖析c++的異常機制。
#include "stdafx.h"
#include<stdlib.h>
#include<crtdbg.h>
#include <iostream>
// 內存洩漏檢測機制
#define _CRTDBG_MAP_ALLOC
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
// 自界說異常類
class MyExcepction
{
public:
// 結構函數,參數為毛病代碼
MyExcepction(int errorId)
{
// 輸入結構函數被挪用信息
std::cout << "MyExcepction is called" << std::endl;
m_errorId = errorId;
}
// 拷貝結構函數
MyExcepction( MyExcepction& myExp)
{
// 輸入拷貝結構函數被挪用信息
std::cout << "copy construct is called" << std::endl;
this->m_errorId = myExp.m_errorId;
}
~MyExcepction()
{
// 輸入析構函數被挪用信息
std::cout << "~MyExcepction is called" << std::endl;
}
// 獲得毛病碼
int getErrorId()
{
return m_errorId;
}
private:
// 毛病碼
int m_errorId;
};
int main(int argc, char* argv[])
{
// 內存洩漏檢測機制
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 可以轉變毛病碼,以便拋出分歧的異常停止測試
int throwErrorCode = 110;
std::cout << " input test code :" << std::endl;
std::cin >> throwErrorCode;
try
{
if ( throwErrorCode == 110)
{
MyExcepction myStru(110);
// 拋出對象的地址 -> 由catch( MyExcepction* pMyExcepction) 捕捉
// 這裡該對象的地址拋出給catch語句,不會挪用對象的拷貝結構函數
// 傳地址是倡導的做法,不會頻仍地挪用該對象的結構函數或拷貝結構函數
// catch語句履行停止後,myStru會被析構失落
throw &myStru;
}
else if ( throwErrorCode == 119 )
{
MyExcepction myStru(119);
// 拋出對象,這裡會經由過程拷貝結構函數創立一個暫時的對象傳出給catch
// 由catch( MyExcepction myExcepction) 捕捉
// 在catch語句中會再次挪用經由過程拷貝結構函數創立暫時對象復制這裡傳曩昔的對象
// throw停止後myStru會被析構失落
throw myStru;
}
else if ( throwErrorCode == 120 )
{
// 不倡導如許的拋出辦法
// 如許做的話,假如catch( MyExcepction* pMyExcepction)中不履行delete操作則會產生內存洩漏
// 由catch( MyExcepction* pMyExcepction) 捕捉
MyExcepction * pMyStru = new MyExcepction(120);
throw pMyStru;
}
else
{
// 直接創立新對象拋出
// 相當於創立了暫時的對象傳遞給了catch語句
// 由catch吸收時經由過程拷貝結構函數再次創立暫時對象吸收傳遞曩昔的對象
// throw停止後兩次創立的暫時對象會被析構失落
throw MyExcepction(throwErrorCode);
}
}
catch( MyExcepction* pMyExcepction)
{
// 輸入本語句被履行信息
std::cout << "履行了 catch( MyExcepction* pMyExcepction) " << std::endl;
// 輸入毛病信息
std::cout << "error Code : " << pMyExcepction->getErrorId()<< std::endl;
// 異常拋出的新對象並不是創立在函數棧上,而是創立在公用的異常棧上,不須要停止delete
//delete pMyExcepction;
}
catch ( MyExcepction myExcepction)
{
// 輸入本語句被履行信息
std::cout << "履行了 catch ( MyExcepction myExcepction) " << std::endl;
// 輸入毛病信息
std::cout << "error Code : " << myExcepction.getErrorId()<< std::endl;
}
catch(...)
{
// 輸入本語句被履行信息
std::cout << "履行了 catch(...) " << std::endl;
// 處置不了,從新拋出給下級
throw ;
}
// 暫停
int temp;
std::cin >> temp;
return 0;
}
常識點: c++異常機制
1、 概述
C++本身有著異常強的糾錯才能,成長到現在,曾經樹立了比擬完美的異常處置機制。C++的異常情形不過兩種,一種是語法毛病,即法式中湧現了毛病的語句,函數,構造和類,導致編譯法式沒法停止。另外一種是運轉時產生的毛病,普通與算法有關。
關於語法毛病,不用多說,寫代碼時心細一點便可以處理。C++編譯器的報錯機制可讓我們輕松地處理這些毛病。
第二種是運轉時的毛病,罕見的有文件翻開掉敗、數組下標溢出、體系內存缺乏等等。而一旦湧現這些成績,激發算法掉效、法式運轉時無故停滯等毛病也是常有的。這就請求我們在設計軟件算法時要周全。好比針對文件翻開掉敗的情形,掩護的辦法有許多種,最簡略的就是應用“return”敕令,告知下層挪用者函數履行掉敗;別的一種處置戰略就是應用c++的異常機制,拋出異常。
2、c++異常處置機制
C++異常處置機制是一個用來有用地處置運轉毛病的異常壯大且靈巧的對象,它供給了更多的彈性、平安性和穩定性,戰勝了傳統辦法所帶來的成績.
異常的拋出和處置重要應用了以下三個症結字: try、 throw 、 catch 。
拋出異常即檢測能否發生異常,在C++中,其采取throw語句來完成,假如檢測到發生異常,則拋出異常。該語句的格局為:
throw 表達式;
假如在try語句塊的法式段中(包含在個中挪用的函數)發明了異常,且擯棄了該異常,則這個異常便可以被try語句塊後的某個catch語句所捕捉並處置,捕捉和處置的前提是被擯棄的異常的類型與catch語句的異常類型相婚配。因為C++應用數據類型來辨別分歧的異常,是以在斷定異常時,throw語句中的表達式的值就沒有現實意義,而表達式的類型就特殊主要。
try-catch語句情勢以下 :
try
{
包括能夠拋出異常的語句;
}
catch(類型名 [形參名]) // 捕捉特定類型的異常
{
}
catch(類型名 [形參名]) // 捕捉特定類型的異常
{
}
catch(...) // 三個點則表現捕捉一切類型的異常
{
}
【典范1】處置除數為0的異常。該典范將上述除數為0的異常可以用try/catch語句來捕捉異常,並應用throw語句來拋出異常,從而完成異常處置,完成代碼如代碼清單1-1所示。
// 代碼清單1-1
#include<iostream.h> //包括頭文件
#include<stdlib.h>
double fuc(double x, double y) //界說函數
{
if(y==0)
{
throw y; //除數為0,拋出異常
}
return x/y; //不然前往兩個數的商
}
void main()
{
double res;
try //界說異常
{
res=fuc(2,3);
cout<<"The result of x/y is : "<<res<<endl;
res=fuc(4,0); 湧現異常,函數外部會拋出異常
}
catch(double) //捕捉並處置異常
{
cerr<<"error of dividing zero.\n";
exit(1); //異常加入法式
}
}
【典范2】自界說異常類型 (在本文開端的代碼中曾經給出示范)
3、異常的接口聲明
為了增強法式的可讀性,使函數的用戶可以或許便利地曉得所應用的函數會拋出哪些異常,可以在函數的聲明中列出這個函數能夠拋出的一切異常類型,例如:
void fun() throw( A,B,C,D);
這注解函數fun()能夠而且只能夠拋出類型(A,B,C,D)及其子類型的異常。
假如在函數的聲明中沒有包含異常的接口聲明,則此函數可以拋出任何類型的異常,例如: void fun();
一個不會拋出任何類型異常的函數可以停止以下情勢的聲明:
void fun() thow();
5、異常處置中須要留意的成績
1. 假如拋出的異常一向沒有函數捕捉(catch),則會一向上傳到c++運轉體系那邊,招致全部法式的終止
2. 普通在異常拋出後資本可以正常被釋放,但留意假如在類的結構函數中拋出異常,體系是不會挪用它的析構函數的,處置辦法是:假如在結構函數中要拋出異常,則在拋出前要記得刪除請求的資本。
3. 異常處置僅僅經由過程類型而不是經由過程值來婚配的,所以catch塊的參數可以沒有參數稱號,只須要參數類型。
4. 函數原型中的異常解釋要與完成中的異常解釋分歧,不然輕易惹起異常抵觸。
5. 應當在throw語句後寫上異常對象時,throw先經由過程Copy結構函數結構一個新對象,再把該新對象傳遞給 catch.
那末當異常拋出後新對象若何釋放?
異常處置機制包管:異常拋出的新對象並不是創立在函數棧上,而是創立在公用的異常棧上,是以它才可以跨接多個函數而傳遞到下層,不然在棧清空的進程中就會被燒毀。一切從try到throw語句之間結構起來的對象的析構函數將被主動挪用。但假如一向上溯到main函數後還沒有找到婚配的catch塊,那末體系挪用terminate()終止全部法式,這類情形下不克不及包管一切部分對象會被准確地燒毀。
6. catch塊的參數推舉采取地址傳遞而不是值傳遞,不只可以進步效力,還可以應用對象的多態性。別的,派生類的異常撲獲要放到父類異常撲獲的後面,不然,派生類的異常沒法被撲獲。
7. 編寫異常解釋時,要確保派生類成員函數的異常解釋和基類成員函數的異常解釋分歧,即派生類改寫的虛函數的異常解釋至多要和對應的基類虛函數的異常解釋雷同,乃至加倍嚴厲,更特別。