cpp異常詳解

sld666666發表於2014-11-11

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++中就是一個能引起口水的問題, 用還是不用?好吧我的意見就是:想用就用。

相關文章