第12集C++的異常對象按指針方式被傳遞

字號:

上兩篇文章分別詳細討論了C++的異常對象按值傳遞和按引用傳遞的兩種方式,本文繼續(xù)討論最后的一種的方式:按指針傳遞。
    異常對象在什么時候構造?
    1、與按值和按引用傳遞異常的方式相比,在按指針傳遞異常的方式下,異常對象的構造方式有很大的不同。它必須是在堆中動態(tài)構造的異常對象,或者是全局性static的變量。示例程序如下:
    void main()
    {
    try
    {
    // 動態(tài)在堆中構造的異常對象
    throw new MyMemoryException("ex_obj1");
    }
    catch(MyException* e)
    {
    cout<GetName()<    delete e;
    }
    }
    2、注意,通過指針方式傳遞的異常對象不能是局部變量,否則后果很嚴重,示例如下:
    void main()
    {
    try
    {
    // 局部變量,異常對象
    MyMemoryException ex_obj1("ex_obj1");
    // 拋出一個指針類型的異常
    // 注意:這樣做很危險,因為ex_obj1這個對象離開了這個作用域即
    // 析構銷毀
    throw &ex_obj1;
    }
    catch(MyException* e)
    {
    // 下面語句雖然不會導致程序崩潰,但是e->GetName()取得的結果
    // 也是不對的。
    cout<GetName()<    // 這條語句會導致程序崩潰
    // delete e;
    }
    }
    程序運行的結果是:
    構造一個MyException異常對象,名稱為:ex_obj1
    構造一個MyMemoryException異常對象,名稱為:ex_obj1
    銷毀一個MyMemoryException異常對象,名稱為:ex_obj1
    銷毀一個MyException異常對象,名稱為:ex_obj1
    捕獲到一個MyException*類型的異常,名稱為:
    異常對象按指針方式被傳遞
    指針是歷史悠久的一種數(shù)據(jù)類型形式,這可以追溯到C語言和PASCAL語言中。異常對象按指針方式傳遞,當然更是不會發(fā)生對象的拷貝復制過程。所以這種方式傳遞異常對象是效率的,它從拋出異常、捕獲異常再到異常錯誤處理結束過程中,總共只會發(fā)生的一次對象的構造過程,那就是異常對象最初在堆中的動態(tài)創(chuàng)建時的初始化的構造過程。也看看示例程序吧!如下:
    void main()
    {
    try
    {
    // 動態(tài)在堆中構造的異常對象
    throw new MyMemoryException("ex_obj1");
    }
    // 注意:這里是定義了按指針方式傳遞異常對象
    catch(MyException* e)
    {
    cout<GetName()<    delete e;
    }
    }
    程序運行的結果是:
    構造一個MyException異常對象,名稱為:ex_obj1
    構造一個MyMemoryException異常對象,名稱為:ex_obj1
    捕獲到一個MyException*類型的異常,名稱為:ex_obj1
    銷毀一個MyMemoryException異常對象,名稱為:ex_obj1
    銷毀一個MyException異常對象,名稱為:ex_obj1
    呵呵!程序的運行結果是不是顯示出異常對象只有一次的構造過程。挺好挺好!
    異常對象什么時候被銷毀
    異常對象動態(tài)地在堆上被創(chuàng)建,同時它也要動態(tài)的被銷毀,否則就必然會發(fā)生內存泄漏。那么異常對象應該在什么時候被銷毀比較合適呢?當然應該是在catch block塊中處理完畢后再銷毀它才比較合理。示例如下:
    void main()
    {
    try
    {
    // 動態(tài)在堆中構造的異常對象
    throw new MyMemoryException("ex_obj1");
    }
    catch(MyException* e)
    {
    cout<GetName()<    // 這里需要顯示的刪除異常對象
    delete e;
    }
    }
    指針方式下,異常對象會發(fā)生對象切片嗎?
    當然不會,試都不用試,阿愚非常有把握確信這一點。
    總結
    (1) 被拋出的異常對象不能是局部變量或臨時變量,必須是在堆中動態(tài)構造的異常對象,或者是全局性static的變量;
    (2) 異常對象只會被構造一次;
    (3) catch 后面帶的異常對象的作用域僅限于catch bock中;
    (4) 異常對象動態(tài)地在堆上被創(chuàng)建,同時它也要動態(tài)的被銷毀。
    至此為止,C++的異常對象的傳遞的三種方式(指針、傳值和引用)都已經討論過了,主人公阿愚到此算是松了一大口氣,終于把這塊比較難肯一點的骨頭給拿下了(呵呵!^_^)。為了更進一步鞏固這些知識。下一篇文章準備對這三種方式來一個綜合性的大比較!去看看吧!