2011-07-20 44 views
15

我有一個愚蠢的問題。我讀這篇文章有關的std ::例外http://www.cplusplus.com/doc/tutorial/exceptions/通過引用捕獲std :: exception?

catch (exception& e),它說:

我們已經把通過引用捕獲異常對象的處理程序(注意類型後的符號&),因此該捕獲也從異常中派生出來的類,比如myexception類的myex對象。

這是否意味着通過使用「&」您還可以捕獲父類的異常?我認爲&是在std :: exception中預定義的,因爲最好傳遞e(std :: exception)作爲引用而不是對象。

+0

我不明白你的最後一段。按引用傳遞與異常無關,並且在C++中基本允許運行時多態。 –

+1

答案是否定的 - 您可以捕獲的對象必須來自您捕獲的異常類型,正如您在文章中提到的那樣。這表現出IS-A關係。如果您只在catch子句中指定子項,則無法捕獲父類。 – Chris

回答

47

之所以使用&例外與其說多態性作爲避免slicing。如果您不使用&,C++會嘗試將拋出的異常複製到新創建的std::exception中,這可能會丟失該進程中的信息。例如:

#include <stdexcept> 
#include <iostream> 

class my_exception : public std::exception { 
    virtual const char *what() const throw() { 
    return "Hello, world!"; 
    } 
}; 

int main() { 
    try { 
    throw my_exception(); 
    } catch (std::exception e) { 
    std::cout << e.what() << std::endl; 
    } 
    return 0; 
} 

這將打印默認消息std::exception(在我的情況,St9exception),而不是Hello, world!,因爲原來的異常對象被切片丟失。如果我們改變一個&

#include <stdexcept> 
#include <iostream> 

class my_exception : public std::exception { 
    virtual const char *what() const throw() { 
    return "Hello, world!"; 
    } 
}; 

int main() { 
    try { 
    throw my_exception(); 
    } catch (std::exception &e) { 
    std::cout << e.what() << std::endl; 
    } 
    return 0; 
} 

現在我們看到Hello, world!

+3

+1;哇,你的例子和答案看起來非常像我的。你坐在我後面嗎? ;) –

+0

@Merlyn,不,我認爲這只是最簡單的方式來演示問題:) – bdonlan

+1

+ bdonlan我不明白'虛擬const char *什麼()const throw(){'兩個函數? what()和throw()可以解釋函數的這種語法。我以前沒有見過。 – AbhimanyuAryan

0

在這裏使用引用異常可以減少創建的臨時對象,也可以保持多態性。

2

不,&絕對不影響異常處理程序的多態性。他們的措辭非常差,似乎表明&是負責任的。不是這種情況。你是對的,&只是通過參考,這是一個更有效的。

另外作爲一般規則, you should really try to avoid cplusplus.com

更新的鏈接:What's wrong with cplusplus.com

+0

切片比效率更重要... – bdonlan

+0

鏈接被破壞? – sje397

+0

@ sje397嗯,看起來他們刪除了文章,我更新了鏈接。 –

7

這是否意味着,通過使用「&」你也可以趕上父類的異常?

不,這不會增加從哪裏(例如,從包含try/catch代碼的類的父類)捕獲異常的範圍。

它也不會增加的類型,可以被捕獲,相比於價值捕獲異常的(不&catch(std::exception e) - 你仍然會抓住每個異常,要麼是std::exception或提煉出來的)。

它增加的是您捕獲異常時實際獲得的數據量。

如果從std::exception派生出一個異常,並且您通過值來捕獲異常,那麼您將拋出該異常類中的任何額外行爲。由於Slicing,它在異常類上破壞polymorphism

一個例子:

class MyException : public std::exception 
{ 
public: 
    virtual const char* what() const 
    { 
     return "hello, from my exception!"; 
    } 
}; 

// ... 

try 
{ 
    throw MyException(); 
} 
catch(std::exception& e) 
{ 
    // This will print "hello, from my exception!" 
    std::cout << e.what() << "\n"; 
} 

// ... 

try 
{ 
    throw MyException(); 
} 
catch(std::exception e) 
{ 
    // This will print "Unknown exception" 
    std::cout << e.what() << "\n"; 
} 
相關問題