例外狀況:3.0 版例外狀況巨集的變更
這是進階主題。
在 MFC 3.0 版和更新版本中,例外狀況處理宏已變更為使用 C++ 例外狀況。 本文說明這些變更如何影響使用宏的現有程式程式碼為。
本文涵蓋下列主題:
例外狀況類型和 CATCH 宏
在舊版的 MFC 中 ,CATCH 宏會使用 MFC 執行時間類型資訊來判斷例外狀況的類型;例外狀況的類型會決定在 catch 網站。 不過,使用 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));
為 true,第一個 catch 區塊會攔截例外狀況。 在 3.0 版中,使用 C++ 例外狀況來實作許多例外狀況處理宏,第二個 catch 區塊符合擲回 CException
的 。
這類程式碼並不常見。 當例外狀況物件傳遞至另一個接受泛型 CException*
的函式時,它通常會顯示,它會執行「預先擲回」處理,最後擲回例外狀況。
若要解決此問題,請將 throw 運算式從 函式移至呼叫的程式碼,並在產生例外狀況時擲回編譯器已知的實際類型例外狀況。
重新擲回例外狀況
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
。
如需詳細資訊,請參閱 例外狀況:攔截和刪除例外狀況 。