C++ 異常處置 catch(...)引見。本站提示廣大學習愛好者:(C++ 異常處置 catch(...)引見)文章只能為提供參考,不一定能成為您想要的結果。以下是C++ 異常處置 catch(...)引見正文
假如要想使一個catch block能抓獲多種數據類型的異常對象的話,怎樣辦?C++尺度中界說了一種特別的catch用法,那就是” catch(…)”。
理性熟悉
1、catch(…)究竟是一個甚麼樣的東東,先來個理性熟悉吧!
看例子先:
int main()
{
try
{
cout << "在 try block 中, 預備拋出一個異常." << endl;
//這裡拋出一個異常(個中異常對象的數據類型是int,值為1)
throw 1;
}
//catch( int& value )
//留意這裡catch語句
catch( …)
{
cout << "在 catch(…) block 中, 拋出的int類型的異常對象被處置" << endl;
}
}
2、哈哈!int類型的異常被catch(…)抓獲了,再來另外一個例子:
int main()
{
try
{
cout << "在 try block 中, 預備拋出一個異常." << endl;
//這裡拋出一個異常(個中異常對象的數據類型是double,值為0.5)
throw 0.5;
}
//catch( double& value )
//留意這裡catch語句
catch( …)
{
cout << "在 catch(…) block 中, double類型的異常對象也被處置" << endl;
}
}
3、異樣,double類型的異常對象也被catch(…)塊抓獲了。是的,catch(..)能婚配勝利一切的數據類型的異常對象,包含C++說話提 供一切的原生數據類型的異常對象,如int、double,還有char*、int*如許的指針類型,別的還稀有組類型的異常對象。同時也包含一切自界說 的籠統數據類型。例程以下:
int main()
{
try
{
cout << "在 try block 中, 預備拋出一個異常." << endl;
//這裡拋出一個異常(個中異常對象的數據類型是char*)
char* p=0;
throw p;
}
//catch( char* value )
//留意這裡catch語句
catch( …)
{
cout << "在 catch(…) block 中, char*類型的異常對象也被處置" << endl;
}
}
int main()
{
try
{
cout << "在 try block 中, 預備拋出一個異常." << endl;
//這裡拋出一個異常(個中異常對象的數據類型是int[])
int a[4];
throw a;
}
//catch( int value[] )
//留意這裡catch語句
catch( …)
{
cout << "在 catch(…) block 中, int[]類型的異常對象也被處置" << endl;
}
}
4、關於籠統數據類型的異常對象。catch(…)異樣有用,例程以下:
class MyException
{
public:
protected:
int code;
};
int main()
{
try
{
cout << "在 try block 中, 預備拋出一個異常." << endl;
//這裡拋出一個異常(個中異常對象的數據類型是MyException)
throw MyException();
}
//catch(MyException& value )
//留意這裡catch語句
catch( …)
{
cout << "在catch(…) block中, MyException類型的異常對象被處置" << endl;
}
}
對catch(…)有點含混?
1、畢竟對catch(…)有甚麼含混呢?照樣看例子先吧!
void main()
{
int* p = 0;
try
{
// 留意:上面這條語句固然不是throw語句,但它在履行時會招致體系
// 湧現一個存儲掩護毛病的異常(access violation exception)
*p = 13; // causes an access violation exception;
}
catch(...)
{
//catch(…)能抓獲住下面的access violation exception異常嗎?
cout << "在catch(…) block中" << endl;
}
}
請問下面的法式運轉時會湧現甚麼成果嗎?catch(…)能抓獲住體系中湧現的access violation exception異常嗎?同伙們!和我們的主人公阿愚一樣,本身著手去測試一把!
成果又若何呢?現實上它有兩種分歧的運轉成果,在window2000體系下用VC來測試運轉這個小法式時,發明法式能輸入"在catch(…) block中"的語句在屏幕上,也即catch(…) 能勝利抓獲住體系中湧現的access violation exception異常,很凶猛吧!但假如這個異樣的法式在linux下用gcc編譯後運轉時,法式將會湧現瓦解,並在屏幕上輸入”segment fault”的毛病信息。
主人公阿愚有點急了,也開端有點含混了,為何?為何?為何異樣一個法式在兩種分歧的體系上有分歧的表示呢?其緣由就是:關於這類因為硬件或操作 體系湧現的體系異常(例如說被零除、內存存儲掌握異常、頁毛病等等)時,window2000體系有一個叫做構造化異常處置(Structured Exception Handling,SEH)的機制,這個東東太凶猛了,它能和VC中的C++異常處置模子很好的聯合上(現實上VC完成的C++異常處置模子很年夜水平上建 立在SEH機制之上的,或許說它是SEH的擴大,前面文章中會具體論述並剖析這個久富盛名的SEH,看看catch(…)是若何奇異接收住這類體系異常出 現後的法式掌握流的,不外這都是後話)。而在linux體系下,體系異常是由旌旗燈號處置編程辦法來掌握的(旌旗燈號處置編程,signal processing progamming。在引見unix和linux下若何編程的書本中,都邑有對旌旗燈號處置編程具體的引見,固然執著的主人公阿愚確定對它也不會放過,會深 入到unix因循上去的旌旗燈號處置編程外部的完成機制,並測驗考試完美改良它,使它也可以或許較好地和C++異常處置模子聯合上)。
那末C++尺度中關於這類統一個法式有分歧的運轉成果有何說明呢?這裡須要留意的是,window2000體系下catch(…)能捕捉住體系異常, 這完整是它本身的擴大。在C++尺度中並沒有請求到這一點,它只劃定catch(…)必需能捕捉法式中一切經由過程throw語句拋出的異常。是以下面的這個 法式在linux體系下的運轉成果也完整是相符C++尺度的。固然年夜家也必需認可window2000體系下對C++異常處置模子的這類擴大確切是一個很 不錯的完美,極年夜得進步了法式的平安性。
為何要用catch(…)這個東東?
法式員同伙們或許會說,這還有問嗎?這篇文章的一開端不就講到了嗎?catch(…)可以或許捕捉多種數據類型的異常對象,所以它供給給法式員一種對異常 對象更好的掌握手腕,使開辟的軟件體系有很好的靠得住性。是以一個比擬有經歷的法式員平日會如許組織編寫它的代碼模塊,以下:
void Func()
{
try
{
// 這裡的法式代碼完成真正龐雜的盤算任務,這些代碼在履行進程中
// 有能夠拋出DataType1、DataType2和DataType3類型的異常對象。
}
catch(DataType1& d1)
{
}
catch(DataType2& d2)
{
}
catch(DataType3& d3)
{
}
// 留意下面try block中能夠拋出的DataType1、DataType2和DataType3三
// 品種型的異常對象在後面都曾經有對應的catch block來處置。但為何
// 還要在最初再界說一個catch(…) block呢?這就是為了有更好的平安性和
// 靠得住性,防止下面的try block拋出了其它未斟酌到的異常對象時招致的程
// 序湧現不測瓦解的嚴重效果,並且這在用VC開辟的體系上更特殊有用,因
// 為catch(…)能捕捉體系湧現的異常,而體系異常常常令法式員頭痛了,現
// 在體系普通都比擬龐雜,並且由許多人配合開辟,一不當心就會招致一個
// 指針變量指向了其它不法區域,成果不測災害不幸產生了。catch(…)為這類
// 潛伏的隱患供給了一種有用的解救辦法。
catch(…)
{
}
}
還有,特殊是VC法式員為了使開辟的體系有更好的靠得住性,常常在運用法式的進口函數中(如MFC框架的開辟情況下 CXXXApp::InitInstance())和任務線程的進口函數中加上一個頂層的trycatch塊,而且應用catch(…)來捕捉一切一切的 異常,以下:
BOOL CXXXApp::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// 留意這裡有一個頂層的trycatch塊,而且應用catch(…)來捕捉一切一切的異常
try
{
CXXXDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
}
catch(…)
{
// dump出體系的一些主要信息,並告訴治理員查找湧現不測異常的緣由。
// 同時想方法恢復體系,例如說從新啟動運用法式等
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
經由過程下面的例程和剖析可以得出,因為catch(…)可以或許捕捉一切數據類型的異常對象,所以在適當的處所應用catch(…)確切可使軟件體系有著更 好的靠得住性。這確切是年夜家應用catch(…)這個東東最好的來由。但不要誤解的是,在C++異常處置模子中,不只要catch(…)辦法可以或許捕捉簡直所 有類型的異常對象.