异常的使用心得
工欲善其事,必先利其器.在做一個(gè)項(xiàng)目時(shí)必定要先做好調(diào)試除錯(cuò)的準(zhǔn)備在面向過(guò)程編程的時(shí)代都是以檢測(cè)
返回的錯(cuò)誤代碼來(lái)判斷錯(cuò)誤,可是這種方法的缺點(diǎn)是如果編寫(xiě)某一操作的時(shí)候可能出現(xiàn)的錯(cuò)誤代碼(比如說(shuō)
硬件操作)太多,那么最終用戶將會(huì)陷入倒無(wú)窮無(wú)盡的檢測(cè)代碼中,可能會(huì)是這個(gè)樣子
UINT err=Functionxx(...);
if(err==xxx)
...
if(err==xxx)
...
...
...
省略100行
只有這樣程序才能在出現(xiàn)意外的時(shí)候有所相應(yīng)和恢復(fù),但是由于錯(cuò)誤處理太龐大了最終用戶很可能這樣
if(Functionxx()!=SUCEEDED)
exit(0);
這樣某些可能可以恢復(fù)的操作也無(wú)法幸免了,(比如說(shuō)網(wǎng)絡(luò)連接超時(shí),終止運(yùn)行太過(guò)分了吧,只要彈出個(gè)對(duì)話
框就行了)
在面向?qū)ο缶幊痰臅r(shí)候,不可否認(rèn),很多人仍然還是這樣排錯(cuò)的,其實(shí)各種面向?qū)ο蟮恼Z(yǔ)言都提供了異常處
理的手段(比如說(shuō)Object Pascal,C++,本文以C++為例)??
下面是我的關(guān)于異常的一些使用心得
對(duì)于各種用戶來(lái)說(shuō),并不是每一種錯(cuò)誤都是他關(guān)心的,特別是小組開(kāi)發(fā)的時(shí)候比如某一模塊是關(guān)于文件操作
的,那么編寫(xiě)這個(gè)模塊的程序員只要注意關(guān)于文件操作失敗的異常就行了,而網(wǎng)絡(luò)模塊的程序員只要知道網(wǎng)
絡(luò)出錯(cuò)的錯(cuò)誤處理就行了,因此,我們可以定義一個(gè)這樣的類(lèi)
class CBasicException
{
CBasicException(...);
char* GetDescription();
UINT GetErrorCode();
...
};
然后再?gòu)倪@個(gè)類(lèi)繼承幾個(gè)子類(lèi)
CFileException,CNetException...
然后和具體某一類(lèi)錯(cuò)誤相關(guān)的詳細(xì)的異常分別從上面的類(lèi)里面繼承,比如文件打開(kāi)失敗,空間不夠...等等
可以從CFileException繼承,而連接超時(shí)..等等可以從CNetException繼承,如此一來(lái)就將錯(cuò)誤分類(lèi)了整個(gè)
類(lèi)層次是這樣的
CBasicException
/ /
CFileException CNetException
/ / / /??
COpenFailed ... CTimeOut ...
之后將各個(gè)錯(cuò)誤碼和相應(yīng)的異常對(duì)應(yīng)起來(lái),一些不太重要的信息可以封裝在一個(gè)異常里,比如文件打不開(kāi)可
能是空間不夠或共享沖突...,都可以放在一起,如果以后要專(zhuān)門(mén)處理某一樣,比如空間不夠,再?gòu)南鄳?yīng)的基
類(lèi)繼承即可(COpenFialed)
然后你的函數(shù)應(yīng)該這樣實(shí)現(xiàn)
CMyfunc()
{
...
throw Cxxx(...);
}
而在相應(yīng)的調(diào)用部分則可以這樣寫(xiě)
void Operation1()
{
try{
Myfunc()
}
catch(CFileException& e)//處理文件
{
printf("%s",e.GetDescription());
throw;//重新拋出,如果搞定就不用再拋出了
}
catch(CNetException& e)//網(wǎng)絡(luò)
{
...
throw;
}
}
這樣只要catch想要處理的異常就行了
但是你的主函數(shù)應(yīng)該這樣寫(xiě)
void main()
{
try{
Opertion1();
Operation2();
Operation.....
...
}
catch(Cxxx& e)//處理未捕獲的重要異常
{
...
}
catch(CBasicException& e)//對(duì)你所封裝的錯(cuò)誤總的處理??
{
...
}
catch(...)//其他異常,未被封裝,比如除0
{
...
}
}
這樣處理就合理多了
而且如果在異常的描述里加上出錯(cuò)地點(diǎn)就更好了,比如出錯(cuò)函數(shù)名
不過(guò)千萬(wàn)不要將異常基類(lèi)的catch寫(xiě)在子類(lèi)的上面否則子類(lèi)的catch可能永遠(yuǎn)不會(huì)工作了??
比如:
try{
...
}
catch(CBasicException& e)
{
...
}
catch(CFileException(& e)
{
...
}
這樣后面的catch就再也不會(huì)被執(zhí)行了
另外在類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)里不能返回值的,這時(shí)就只能用異常了 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
返回的錯(cuò)誤代碼來(lái)判斷錯(cuò)誤,可是這種方法的缺點(diǎn)是如果編寫(xiě)某一操作的時(shí)候可能出現(xiàn)的錯(cuò)誤代碼(比如說(shuō)
硬件操作)太多,那么最終用戶將會(huì)陷入倒無(wú)窮無(wú)盡的檢測(cè)代碼中,可能會(huì)是這個(gè)樣子
UINT err=Functionxx(...);
if(err==xxx)
...
if(err==xxx)
...
...
...
省略100行
只有這樣程序才能在出現(xiàn)意外的時(shí)候有所相應(yīng)和恢復(fù),但是由于錯(cuò)誤處理太龐大了最終用戶很可能這樣
if(Functionxx()!=SUCEEDED)
exit(0);
這樣某些可能可以恢復(fù)的操作也無(wú)法幸免了,(比如說(shuō)網(wǎng)絡(luò)連接超時(shí),終止運(yùn)行太過(guò)分了吧,只要彈出個(gè)對(duì)話
框就行了)
在面向?qū)ο缶幊痰臅r(shí)候,不可否認(rèn),很多人仍然還是這樣排錯(cuò)的,其實(shí)各種面向?qū)ο蟮恼Z(yǔ)言都提供了異常處
理的手段(比如說(shuō)Object Pascal,C++,本文以C++為例)??
下面是我的關(guān)于異常的一些使用心得
對(duì)于各種用戶來(lái)說(shuō),并不是每一種錯(cuò)誤都是他關(guān)心的,特別是小組開(kāi)發(fā)的時(shí)候比如某一模塊是關(guān)于文件操作
的,那么編寫(xiě)這個(gè)模塊的程序員只要注意關(guān)于文件操作失敗的異常就行了,而網(wǎng)絡(luò)模塊的程序員只要知道網(wǎng)
絡(luò)出錯(cuò)的錯(cuò)誤處理就行了,因此,我們可以定義一個(gè)這樣的類(lèi)
class CBasicException
{
CBasicException(...);
char* GetDescription();
UINT GetErrorCode();
...
};
然后再?gòu)倪@個(gè)類(lèi)繼承幾個(gè)子類(lèi)
CFileException,CNetException...
然后和具體某一類(lèi)錯(cuò)誤相關(guān)的詳細(xì)的異常分別從上面的類(lèi)里面繼承,比如文件打開(kāi)失敗,空間不夠...等等
可以從CFileException繼承,而連接超時(shí)..等等可以從CNetException繼承,如此一來(lái)就將錯(cuò)誤分類(lèi)了整個(gè)
類(lèi)層次是這樣的
CBasicException
/ /
CFileException CNetException
/ / / /??
COpenFailed ... CTimeOut ...
之后將各個(gè)錯(cuò)誤碼和相應(yīng)的異常對(duì)應(yīng)起來(lái),一些不太重要的信息可以封裝在一個(gè)異常里,比如文件打不開(kāi)可
能是空間不夠或共享沖突...,都可以放在一起,如果以后要專(zhuān)門(mén)處理某一樣,比如空間不夠,再?gòu)南鄳?yīng)的基
類(lèi)繼承即可(COpenFialed)
然后你的函數(shù)應(yīng)該這樣實(shí)現(xiàn)
CMyfunc()
{
...
throw Cxxx(...);
}
而在相應(yīng)的調(diào)用部分則可以這樣寫(xiě)
void Operation1()
{
try{
Myfunc()
}
catch(CFileException& e)//處理文件
{
printf("%s",e.GetDescription());
throw;//重新拋出,如果搞定就不用再拋出了
}
catch(CNetException& e)//網(wǎng)絡(luò)
{
...
throw;
}
}
這樣只要catch想要處理的異常就行了
但是你的主函數(shù)應(yīng)該這樣寫(xiě)
void main()
{
try{
Opertion1();
Operation2();
Operation.....
...
}
catch(Cxxx& e)//處理未捕獲的重要異常
{
...
}
catch(CBasicException& e)//對(duì)你所封裝的錯(cuò)誤總的處理??
{
...
}
catch(...)//其他異常,未被封裝,比如除0
{
...
}
}
這樣處理就合理多了
而且如果在異常的描述里加上出錯(cuò)地點(diǎn)就更好了,比如出錯(cuò)函數(shù)名
不過(guò)千萬(wàn)不要將異常基類(lèi)的catch寫(xiě)在子類(lèi)的上面否則子類(lèi)的catch可能永遠(yuǎn)不會(huì)工作了??
比如:
try{
...
}
catch(CBasicException& e)
{
...
}
catch(CFileException(& e)
{
...
}
這樣后面的catch就再也不會(huì)被執(zhí)行了
另外在類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)里不能返回值的,這時(shí)就只能用異常了 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
- 上一篇: Spatial Pyramid Pool
- 下一篇: 最大似然估计(MLE:样本观测总体参数)