1. 異常介紹
在函式在執行過程中如果碰到對錯誤的處理可以有兩種方式, 1. 返回錯誤,2. 使用異常。 如果作為函式的呼叫者想要知道具體的錯誤資訊, 就需要維護一套錯誤列表, 或者用string型別的返回。顯然這兩種使用起來都不那麼方便。
C++中處理異常的過程是這樣的:在執行程式發生異常,可以不在本函式中處理,而是丟擲一個錯誤資訊,把它傳遞給上一級的函式來解決,上一級解決不了,再傳給其上一級,由其上一級處理。如此逐級上傳,直到最高一級還無法處理的話,執行系統會自動呼叫系統函式terminate,由它呼叫abort終止程式。這樣的異常處理方法使得異常引發和處理機制分離,而不在同一個函式中處理。這使得底層函式只需要解決實際的任務,而不必過多考慮對異常的處理,而把異常處理的任務交給上一層函式去處理。
2. 使用介紹
c++的異常處理機制由三部分組成:try(檢查), throw(丟擲),catch(捕獲)。最典型的用法如下:
void doThrow(){
throw std::string("throw everything");
}
void testException(){
try
{
doThrow();
}
catch (std::string e){
std::cout << e << std::endl;
}
catch (...)
{
std::cout << "exception" << std::endl;
}
}
throw 可以任何東西,catch也可以捕捉然後exception.
3. 進一步用法
當然程式設計中有一個非常重要的約定就是“約束”。我們要對能丟擲的異常能進行約束, 所以標準庫提供了一個類std::exception 來給我們繼承使用。exception 中一個最重要的函式是:
class exception{
virtual const char * __CLR_OR_THIS_CALL what() const _THROW0()
{ // return pointer to message string
return (_Ptr != 0 ? _Ptr : "unknown exception");
}
}
我們可以過載它,然後丟擲自己的錯誤資訊。舉個例子:
class ParserException : public std::exception
{
public:
ParserException(const char *what, void *where)
: m_what(what)
, m_where(where)
{
}
virtual const char *what() const throw()
{
return m_what;
}
template<class Ch>
Ch *where() const
{
return reinterpret_cast<Ch *>(m_where);
}
private:
const char *m_what;
void *m_where;
};
#define PARSE_ERROR(what, where) throw ParserException(what, where)
void doThrow(){
PARSE_ERROR("throw everything", nullptr);
}
void testException(){
try
{
doThrow();
}
catch (ParserException e){
std::cout << e.what() << std::endl;
}
}
好吧, 其實換湯不換藥。
4. 總結
本文主要介紹了c++異常的典型使用方法。
異常時一種常見的錯誤處理方法,它可以把錯誤從程式的邏輯處理中剝離出來。當然顯然,異常在c++中就是一個能引起口水的問題, 用還是不用?好吧我的意見就是:想用就用。