C++中異常處置的根本思惟及throw語句拋出異常的應用。本站提示廣大學習愛好者:(C++中異常處置的根本思惟及throw語句拋出異常的應用)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中異常處置的根本思惟及throw語句拋出異常的應用正文
異常處置根本思惟
C++的異常處置的根本思惟年夜致可以歸納綜合為傳統毛病處置機制、經由過程函數前往值來處置毛病。
1)C++的異常處置機制使得異常的激發和異常的處置不用在統一個函數中,如許底層的函數可以側重處理詳細成績,而不用過量的斟酌異常的處置。下層挪用者可以再恰當的地位設計對分歧類型異常的處置。
2)異常是專門針對籠統編程中的一系列毛病處置的,C++中不克不及借助函數機制,由於棧構造的實質是先輩後出,順次拜訪,沒法停止騰躍,但毛病處置的特點倒是碰到毛病信息就想要轉到若干級之長進行從新測驗考試,如圖
3)異常超脫於函數機制,決議了其對函數的逾越式回跳。
4)異常逾越函數
異常根本語法
1) 如有異常則經由過程throw操作創立一個異常對象並拋擲。
2) 將能夠拋出異常的法式段嵌在try塊當中。掌握經由過程正常的次序履行達到try語句,然後履行try塊內的掩護段。
3) 假如在掩護段履行時代沒有惹起異常,那末跟在try塊後的catch子句就不履行。法式從try塊後追隨的最初一個catch子句前面的語句持續履行下去。
4) catch子句按其在try塊後湧現的次序被檢討。婚配的catch子句將捕捉並處置異常(或持續拋擲異常)。
5) 假如婚配的處置器未找到,則運轉函數terminate將被主動挪用,其缺省功效是挪用abort終止法式。
6)處置不了的異常,可以在catch的最初一個分支,應用throw語法,向上扔
7)異常機制與函數機制互不干預,但捕獲的方法是基於類型婚配。捕獲相當於函數前往類型的婚配,而不是函數參數的婚配,所以捕獲不消斟酌一個拋命中的多種數據類型婚配成績。
catch代碼塊必需湧現在try後,而且在try塊後可以湧現多個catch代碼塊,以捕獲各類分歧類型的拋擲。
異常機制是基於如許的道理:法式運轉本質上是數據實體在做一些操作,是以產生異常景象的處所,必定是某個實體出了錯誤,該實體所對應的數據類型便作為拋擲和捕獲的根據。
8)異常捕獲嚴厲依照類型婚配
異常捕獲的類型婚配之刻薄水平可以和模板的類型婚配媲美,它不許可相容類型的隱式轉換,好比,拋擲char類型用int型就捕獲不到.例以下列代碼不會輸入“int exception.”,從而也不會輸入“That's ok.” 由於湧現異常後提醒加入
int main(){ try{ throw ‘H'; } catch (int){ cout << "int exception.\n"; } cout << "That's ok.\n"; return 0; }
棧解旋(unwinding)
異常被拋出後,從進入try塊起,到異常被拋擲前,這時代在棧上的結構的一切對象,都邑被主動析構。析構的次序與結構的次序相反。這一進程稱為棧的解旋(unwinding)。
#include <iostream> #include <cstdio> using namespace std; class MyException {}; class Test { public: Test(int a = 0, int b = 0) { this->a = a; this->b = b; cout << "Test 結構函數履行" << "a:" << a << " b: " << b << endl; } void printT() { cout << "a:" << a << " b: " << b << endl; } ~Test() { cout << "Test 析構函數履行" << "a:" << a << " b: " << b << endl; } private: int a; int b; }; void myFunc() throw (MyException) { Test t1; Test t2; cout << "界說了兩個棧變量,異常拋出後測試棧變量的若何被析構" << endl; throw MyException(); } int main() { //異常被拋出後,從進入try塊起,到異常被拋擲前,這時代在棧上的結構的一切對象, //都邑被主動析構。析構的次序與結構的次序相反。 //這一進程稱為棧的解旋(unwinding) try { myFunc(); } //catch(MyException &e) //這裡不克不及拜訪異常對象 catch (MyException) //這裡不克不及拜訪異常對象 { cout << "吸收到MyException類型異常" << endl; } catch (...) { cout << "未知類型異常" << endl; } return 0; }
異常接口聲明
1)為了增強法式的可讀性,可以在函數聲明中列出能夠拋出的一切異常類型,例如:
void func() throw (A, B, C , D); //這個函數func()可以或許且只能拋出類型A B C D及其子類型的異常。
2)假如在函數聲明中沒有包括異常接口聲明,則次函數可以拋擲任何類型的異常,例如:
void func();
3)一個不拋擲任何類型異常的函數可以聲明為:
void func() throw();
4) 假如一個函數拋出了它的異常接口聲明所不許可拋出的異常,unexpected函數會被挪用,該函數默許行動挪用terminate函數中斷法式。
傳統處置毛病
#include <iostream> #include <cstdio> using namespace std; // 傳統的毛病處置機制 int myStrcpy(char *to, char *from) { if (from == NULL) { return 1; } if (to == NULL) { return 2; } // copy時的場景檢討 if (*from == 'a') { return 3; // copy時毛病 } while (*from != '\0') { *to = *from; to++; from++; } *to = '\0'; return 0; } int main() { int ret = 0; char buf1[] = "zbcdefg"; char buf2[1024] = { 0 }; ret = myStrcpy(buf2, buf1); if (ret != 0) { switch (ret) { case 1: cout << "源buf失足!\n"; break; case 2: cout << "目標buf失足!\n"; break; case 3: cout << "copy進程失足!\n"; break; default: cout << "未知毛病!\n"; break; } } cout << "buf2:\n" << buf2; cout << endl; return 0; }
throw char*
#include <iostream> #include <cstdio> using namespace std; // throw char * void myStrcpy(char *to, char *from) { if (from == NULL) { throw "源buf失足"; } if (to == NULL) { throw "目標buf失足"; } // copy時的場景檢討 if (*from == 'a') { throw "copy進程失足"; // copy時毛病 } while (*from != '\0') { *to = *from; to++; from++; } *to = '\0'; return; } int main() { int ret = 0; char buf1[] = "abcdefg"; char buf2[1024] = { 0 }; try { myStrcpy(buf2, buf1); } catch (int e) // e可以寫可以不寫 { cout << e << "int類型異常" << endl; } catch (char *e) { cout << "char* 類型異常" << endl; } catch (...) { }; cout << endl; return 0; }
throw 類對象
#include <iostream> #include <cstdio> using namespace std; class BadSrcType {}; class BadDestType {}; class BadProcessType { public: BadProcessType() { cout << "BadProcessType結構函數do \n"; } BadProcessType(const BadProcessType &obj) { cout << "BadProcessType copy結構函數do \n"; } ~BadProcessType() { cout << "BadProcessType析構函數do \n"; } };
throw 類對象、類型異常
void my_strcpy3(char *to, char *from) { if (from == NULL) { throw BadSrcType(); } if (to == NULL) { throw BadDestType(); } //copy是的 場景檢討 if (*from == 'a') { printf("開端 BadProcessType類型異常 \n"); throw BadProcessType(); //會不會發生一個匿名對象? } if (*from == 'b') { throw &(BadProcessType()); //會不會發生一個匿名對象? } if (*from == 'c') { throw new BadProcessType; //會不會發生一個匿名對象? } while (*from != '\0') { *to = *from; to++; from++; } *to = '\0'; } int main() { int ret = 0; char buf1[] = "cbbcdefg"; char buf2[1024] = { 0 }; try { //my_strcpy1(buf2, buf1); //my_strcpy2(buf2, buf1); my_strcpy3(buf2, buf1); } catch (int e) //e可以寫 也能夠不寫 { cout << e << " int類型異常" << endl; } catch (char *e) { cout << e << " char* 類型異常" << endl; } //--- catch (BadSrcType e) { cout << " BadSrcType 類型異常" << endl; } catch (BadDestType e) { cout << " BadDestType 類型異常" << endl; } //結論1: 假如 接收異常的時刻 應用一個異常變量,則copy結構異常變量. /* catch( BadProcessType e) //是把匿名對象copy給e 照樣e照樣誰人匿名對象 { cout << " BadProcessType 類型異常" << endl; } */ /*結論2: 應用援用的話 會應用throw時刻的誰人對象 catch( BadProcessType &e) //是把匿名對象copy給e 照樣e照樣誰人匿名對象 { cout << " BadProcessType 類型異常" << endl; } */ //結論3: 指針可以和援用/元素寫在一塊 然則援用和元素不克不及寫在一塊 catch (BadProcessType *e) //是把匿名對象copy給e 照樣e照樣誰人匿名對象 { cout << " BadProcessType 類型異常" << endl; delete e; } //結論4: 類對象時, 應用援用比擬適合 // -- catch (...) { cout << "未知 類型異常" << endl; } return 0; }