目錄
- C++的異常處理方法知識要點
- 踹扔抓的代碼塊示例
- 兩種處理被0除的方法
- 異常處理機制的優點
- 其他語言中的異常處理
- C++函數異常聲明
C++的異常處理方法知識要點
理解“踹扔抓”三部曲的結構,尤其是catch是怎么匹配異常的。
知道C++標準庫中的異常類都是從exception繼承下來的,并且支持 what() 這個操作
了解logic_error、runtime_error等一些常見的異常類的大致含義,以便于我們自己寫異常類的時候拿來繼承
理解多個catch語句的匹配原則,尤其是對于繼承鏈上的異常類型,哪個在前哪個在后必須做到心里有數
掌握異常傳播的原理:異常如果在當前函數中沒有被捕獲,它就會被拋向當前函數的調用者;拋異常的語句后面的語句都會被跳過,直到遇到對應的catch
踹扔抓的代碼塊示例
try{code to try;throw an exception (1)with a throw statement(2) or from functionMore code to try;
}
catch(type e){Code to process the exception;
}
兩種處理被0除的方法
(1) use if statement (使用if語句)
(2) use exception handling (使用異常處理)
下面是使用異常處理的程序,如果除數是0,那么會拋出number1;執行throw語句之后, 緊隨其后的 cout 語句就會被跳過;
如果能夠抓住number1,那么就會進行處理,不會出現程序出錯。
如果type不匹配,就會抓不住,程序會崩潰。
int main() {// Read two intergerscout << "Enter two integers: ";int number1, number2;cin >> number1 >> number2;try {if (number2 == 0)throw number1;cout << number1 << " / " << number2 <<" is " << (number1 / number2) << endl;}catch (int e) {cout << "Exception: an integer " << e <<" cannot be divided by zero" << endl;}cout << "Execution continues ..." << endl;
}
異常處理機制的優點
可將異常信息從被調函數帶回給主調函數。異常處理實際上是對程序執行流程的控制
如下例:在quotient里面遇到異常,將異常扔出而不對異常進行處理,問題交由主調函數main來處理。從而將異常的發現與處理分開。
//用異常處理
int quotient(int number1, int number2) {if (number2 == 0) throw number1; return number1 / number2;
}
int main() {try {int x = quotient(1, 0);} catch (int) {std::cout << "除數為0!";}
}
若不用異常處理:quotient()如何告訴 main() “number2 有問題”?
我們可以從返回值和傳引用的角度思考,但是若是函數嵌套調用,該如何將異常信息帶回給主調函數
(1) 用返回值?
·f(number2 == 0) return x; //x應該是0還是1?
(2) 用指針/引用類型的參數?然后再主函數去查看這個參數,但是不優雅。
int quotient(int n1, int n2, int &s){ if(n2 == 0) s=-1; //求商,函數要3個參數? }
(3) 如果采用f(g(h(quotient(x,y))));
怎樣將錯誤從quotient() 傳到 f()?若是使用(2),難道要在每個函數加上一個引用類型的參數來讓主調函數查詢是否出現異常嗎?
顯然,在這種情況下用異常處理更加簡潔
其他語言中的異常處理
python中:
try:代碼raise xxx拋出異常
except:錯誤時執行
else:沒有錯誤時執行
finally無論如何都執行
關于java與C++:
在C++中,你可以拋出任何類型的異常。(c++可以拋出任何類型,,java中這樣是不行的).
Java的函數異常聲明是在編譯時刻檢查的,所以如果是java任何調用abc函數的其他函數,java虛擬機會強迫那些調用abc函數的其他函數處理matherr, error這些異常。
而C++編譯在時候,對這些調用 以聲明會拋出異常函數 的其他函數,不會強制他們處理這些可能會拋出的異常。
C++函數異常聲明
1、在函數參數列表后聲明可能會拋出的異常:
C++從某個年代就開始,在函數的后面加上“:”+ throw+“()”,圓括號內有1個或多個異常類,多個用逗號分割。
void abc( int a ) : throw ( matherr, error) {…}
這是告訴別的程序,在abc函數的運行時刻,最多可以拋出圓括號里的哪些個異常類。
2、函數后聲明可能拋出的異常 的 意思:
當前函數運行時刻有可能會拋出的異常,但是保證不會拋出圓括號內matherr, error以外的其他異常。
C++函數異常聲明,不是用來約束那些調用聲明可能會拋出異常abc函數 的其他函數。不是約束其他函數 調用abc 就必須處理matherr, error這些異常。而是用來約束abc函數本身的行為。abc 函數聲明會拋出matherr, error這些異常,如果abc函數運行時拋出了除了matherr, error以外的異常,程序會拋出unexpected(想不到/未知的)異常然后程序終止。
·C++函數后聲明/不聲明異常:
·1、void abc( int a ) {…} //普通函數
普通函數表示可以拋出任何異常
·2、void abc( int a ):throw() {…} // 不拋異常的函數
函數參數后 throw(),圓括號內沒有任何東西,表示這個函數承諾不會拋出任何異常!
·3、void abc( int a ):throw(matherr) {…} //函數會拋出matherr
函數參數后 throw(),圓括號有matherr,表示運行時會有一個機制檢驗這個函數是否真的,只拋出了列表里的matherr異常。
·區別與Java函數后聲明/不聲明異常:
·1、void abc( int a ) {…} //普通函數
普通函數表示不拋出任何異常
·2、void abc( int a ) throw(exception) {…} // 拋出任何異常 函數參數后
throw(),圓括號內有exception,表示這個函數會拋出任何異常!