2014-10-07 65 views
2

我有這個程序,派生類的ctor拋出異常。該程序只是一個示例程序,我只是想了解異常處理的概念。類的構造函數中異常處理的行爲

class A{ 
public: 
    A() {} 

    ~A(){std::cout << "DTOR called - A!!" << std::endl;} 
}; 

class B : public A 
{ 
public: 
    B():A() 
    { 
     try 
     { 
     init(); 
     } 
     catch(...) 
     { 
     std::cout << "Inside catch block in B's Ctor!!" << std::endl; 
     throw this; 
     } 
    } 

    void init() { throw 0; } 

    ~B() {std::cout << "DTOR called - B!!" << std::endl; } 
}; 

int main() 
{ 
    try{ 
     B *b = new B; 

     std::cout << "Äfter B's ctor called in try block!!" << std::endl; 
     delete b; 
     std::cout << "Äfter B's dtor called in try block!!" << std::endl; 
    } 

    catch(B* b) 
    { 
     delete b; 
     b = NULL; 
     std::cout << "Exception Occurred in B!!" << std::endl; 
    } 

    catch(A* a) 
    { 
     delete a; 
     a = NULL; 
     std::cout << "Exception Occurred in A!!" << std::endl; 
    } 

    catch(...) 
    { 
     std::cout << "Exception Occured!!" << std::endl; 
    } 
    return EXIT_SUCCESS; 
} 

預期的輸出是它應該進入B的catch塊,並且應該調用第一個B的dtor,然後調用A的dtor。但上述程序的輸出是:

Inside catch block in B's Ctor!! 
DTOR called - A!! 
DTOR called - B!! 
DTOR called - A!! 
Exception Occurred in B!! 

我想問這是爲什麼A類的析構函數調用了兩次,當它只是引入了B類的catch塊,並呼籲只有B類的析構函數? 也請告訴我是否在這裏犯了一些錯誤。 任何幫助表示讚賞

編輯:

class B : public A 
{ 
public: 
    B():A() 
    { 
     try 
     { 
     szName = new char[100]; 
     init(); 
     } 
     catch(...) 
     { 
     std::cout << "Inside catch block in B's Ctor!!" << std::endl; 
     throw this; 
     } 
    } 

    void init() { throw 0; } 

    ~B() 
    { 
     delete szName; 
     std::cout << "DTOR called - B!!" << std::endl; 
    } 

    char *szName; 
}; 

在這裏,我在構造函數try塊創建了一個字符指針類B.分配的內存被拋出異常之前。現在在這種情況下,如果我沒有發現類B的異常,會不會有內存泄漏?

+0

見http://www.gotw.ca/gotw/066.htm – 2014-10-07 06:33:29

回答

2

~A()被調用兩次的原因是因爲B()體內,A()完全初始化,所以在發生異常時,~A()將自動被調用,而B()本身還沒有完全初始化,因此~B()不會被調用,並且如果構造函數拋出,則不必刪除指針,C++將在這種情況下爲您調用delete。見LIVE DEMO

3

你爲什麼要在你的catch塊中扔「this」?你已經在試圖製造「這個」的時候進行了嘗試,那麼你怎麼能把它扔掉呢?嘗試扔掉你抓到的東西,或者其他的東西,比如「糟糕」。

+0

我扔「本」,否則這將是一個內存泄漏。你將如何刪除分配給「b」的內存呢? – 2014-10-07 06:25:38

+0

不是問題,除非在拋出之前已經在構造函數中分配了某些東西。 – 2014-10-07 06:28:34

+0

@SaurabhBhola:如果構造函數拋出,'new'會自動釋放它分配的內存。沒有必要嘗試自己做。 – 2014-10-07 06:36:21

3

不要拋棄this:在發現異常時,失敗的對象不再存在。它已被清除,析構函數調用其成員和基類,並且其內存由異常處理機制自動解除分配。試圖第二次刪除它是一個錯誤。

就像從任何其他函數中拋出正常的異常類型(最好是std::exception的子類型)。

0

1)B * b = new B;

竣工類的

類B的結構是不完整的

2)拋出此;

它會釋放類的部分,所以〜A()被調用,〜B()不會被調用,因爲它的結構是不完整的

3)控制進入趕上(B * B)

刪除b;

稱爲〜然後B〜一個

相關問題