簡體   English   中英

為什么bad_exception不會自動拋出?

[英]Why bad_exception is not thrown automatically?

為什么這段代碼沒有錯誤運行? 遇到意外異常時,難道不應該自動調用bad_exception嗎? 還是有必要為其設置處理程序?

#include <iostream>
#include <exception>
using namespace std;
class C{};
void test() throw(bad_exception)
{
    throw C();
}
int main()
{
    try
    {
         test();
    } catch(bad_exception& e)
    {
        cout << "Caught ";
    }
}

在C ++ 03理論中:如果引發的異常不在異常規范中,則將調用unexpected() 如果您尚未通過set_unexpected()設置意外的處理程序, set_unexpected()這意味着您將觀察到terminate()被調用的情況。 如果設置一個意想不到的處理程序不調用終止,但拋出一個異常,如果該異常不能在你的異常規范中列出,它被翻譯成bad_exception。 因此,為了獲得預期的結果,請首先使用適當的處理程序調用set_unexpected()

在C ++ 03的實踐中:有些編譯器根本不支持異常規范( throw()除外),其他編譯器只是不評估/檢查其正確性。 正如Herb Sutter指出的那樣 ,異常規范創建了一個笨拙的“影子類型系統”,該系統很難正確處理(如果可能的話)。 因此..

...在C ++ 11中: 不贊成使用 Exception規范。 您寧可不要使用它們。 但是,有一個nothrow運算符的功能與throw()略有不同


PS:那么為什么C ++ 03中有std :: bad_exception? 您擁有三個不同的代碼區域:

  • 您正在為其編寫異常規范的函數。
  • 您從該函數調用的“外部”代碼可能會或可能不會引發與您的規范不匹配的異常。
  • (可能也是未知的)意外的處理程序可以是任何東西,應該終止/退出/中止程序或拋出任何東西。

因此,如果“外來”代碼引發了違反您的異常規范的異常,則可能會產生以下三種結果:

  1. 處理程序終止程序。 除非您在函數中設置自己的處理程序,否則您將無能為力。
  2. 處理程序將引發與您的異常規范匹配的異常。 一切都很好。
  3. 處理程序會拋出其他內容。 您希望運行時現在做什么? 這就是bad_exception出現的地方:如果在您的規范中,則“其他”將轉換為bad_exception,然后程序繼續。 如果不是,則終止被調用。

在函數內設置自己的處理程序將禁用任何其他僅想使用您的函數的人先前設置的處理程序。 他不會期望您禁用他的處理程序。 此外,該處理程序是一種全局的“假設-如果”策略,因此您在單個函數實現中就不必擔心。

這應該調用std::unexpected ,默認情況下調用std::terminate()因為拋出的異常不是異常規范的一部分。

(此處適用於Linux上的g ++,Solaris上的 Sun Oracle CC,AIX BTW上的IBM xlC)

如果您安裝了意外的處理程序,它將按您期望的那樣工作:

include <iostream>
#include <exception>
using namespace std;
class C{};

void myunexpected()
{
    throw std::bad_exception();
}

void test() throw(std::bad_exception)
{
    throw C();
}
int main()
{
    try
    {
        set_unexpected(myunexpected);
        test();
    } catch(std::bad_exception& e)
    {
        std::cout << "Caught ";
    }
}

按照[except.unexpected],當一個函數拋出其動態異常規范中未列出的異常時,將調用std::unexpected() 根據[unexpected.handler], std::unexpected()的默認實現只是調用std::terminate()

但是,程序可以安裝自己的處理程序,該處理程序可以(重新)引發異常。 如果由此引發的異常不會被動態異常規范允許,它可以被替換std::bad_exception 允許的時候。

您的catch塊將僅捕獲bad_exception類型或其子類型的異常。 C不符合此條件。

實際上, 這個問題與您的問題非常相似。 可接受的答案說明,如果您的函數拋出與規范不匹配的異常(如果存在),則將調用std::unexpected ,默認情況下將調用std::terminate

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM