共用方式為


例外狀況:3.0 版例外狀況巨集的變更

這是進階主題。

在 MFC 3.0 版和更新版本中,例外狀況處理巨集已變更為使用C++例外狀況。 本文說明這些變更如何影響使用巨集的現有程式代碼行為。

本文涵蓋下列主題:

例外類型和 CATCH 宏

在舊版 MFC 中,CATCH 巨集使用 MFC 的運行時類型資訊來判斷例外狀況的類型;換句話說,例外狀況的類型是在捕獲點決定的。 不過,使用C++異常時,異常的類型總是在擲出點由擲出異常物件的類型決定。 在罕見情況下,若擲出的物件的指標類型與物件類型不同,這會導致不相容。

下列範例說明 MFC 3.0 版與舊版之間這項差異的結果:

TRY
{
   THROW((CException*) new CCustomException());
}
CATCH(CCustomException, e)
{
   TRACE("MFC 2.x will land here\n");
}
AND_CATCH(CException, e)
{
   TRACE("MFC 3.0 will land here\n");
}
END_CATCH

此程式代碼在 3.0 版中的行為不同,因為控件一律會傳遞至具有相符例外狀況宣告的第一個 catch 區塊。 throw 表達式的結果

THROW((CException*) new CCustomException());

即使它被建構為 CException*,仍會作為 CCustomException 拋出。 MFC 2.5 版和更早版本中的 CATCH 巨集會使用 CObject::IsKindOf 在運行時間測試類型。 因為表達式

e->IsKindOf(RUNTIME_CLASS(CException));

若為真,第一個 catch 區塊會捕捉例外。 在 3.0 版中,使用 C++ 異常來實作許多異常處理巨集,第二個 catch 區塊與拋出的 CException 相匹配。

這類程序代碼並不常見。 當例外狀況對象傳遞至另一個接受泛型 CException*的函式時,它通常會顯示,它會執行「預先擲回」處理,最後擲回例外狀況。

若要解決此問題,請將 throw 運算式從函式移至呼叫端程式碼,並在產生例外狀況時擲回編譯器當時所知的實際類型的例外狀況。

Re-Throwing 例外狀況

catch 區塊無法擲回它所攔截的相同例外狀況指標。

例如,此程式代碼在舊版中有效,但 3.0 版會有非預期的結果:

TRY
{
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)
{
   THROW(e);    // Wrong. Use THROW_LAST() instead
}
END_CATCH
   }

在 catch 區塊中使用 THROW 會導致刪除指標 e ,讓外部 catch 網站會收到無效的指標。 使用 THROW_LAST 重新擲回 e

如需詳細資訊,請參閱 例外狀況:攔截和刪除例外狀況

另請參閱

例外狀況處理