C 結構化例外狀況處理 (SEH) 和C++例外狀況處理的主要差異在於,C++例外狀況處理模型會在類型中處理,而 C 結構化例外狀況處理模型則處理一種類型的例外狀況:具體來說,是 unsigned int。 也就是說,C 例外狀況是由不帶正負號的整數值來識別,而C++例外狀況是由數據類型來識別。 在 C 中引發結構化例外狀況時,每個可能的處理程式都會執行篩選來檢查 C 例外狀況內容,並判斷是否接受例外狀況、將它傳遞至其他處理程式,或忽略它。 C++ 中擲回例外狀況時,它可能是任何類型。
第二個差異在於 C 結構化例外狀況處理模型稱為 異步,因為例外狀況是次要於一般控制流程。 C++例外狀況處理機制是完全 同步的,這表示只有在擲回例外狀況時才會發生例外狀況。
當您使用 /EHs 或 /EHsc 編譯程序選項時,不會C++例外狀況處理程序處理結構化例外狀況。 這些例外狀況只會由 __except 結構化例外狀況處理程式或 __finally 結構化終止處理程序處理。 如需詳細資訊,請參閱結構化例外狀況處理(C/C++)。
在 /EHa 編譯程式選項下,如果在C++程式中引發 C 例外狀況,則可以由結構化例外狀況處理程式及其相關聯的篩選或C++catch處理程式來處理,無論哪一個動態接近例外狀況內容。 例如,此範例C++程式會在C++ try 內容內引發 C 例外狀況:
範例 - 攔截C++ catch 區塊中的 C 例外狀況
// exceptions_Exception_Handling_Differences.cpp
// compile with: /EHa
#include <iostream>
using namespace std;
void SEHFunc( void );
int main() {
try {
SEHFunc();
}
catch( ... ) {
cout << "Caught a C exception."<< endl;
}
}
void SEHFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
cout << "In finally." << endl;
}
}
In finally.
Caught a C exception.
C 例外狀況包裝函式類別
在上述的簡單範例中,C 例外狀況只能由省略號 (...) catch 處理程序攔截。 與該例外狀況類型或特性相關的資訊,都不會傳遞至處理常式。 雖然此方法可運作,但在某些情況下,您可能想要定義兩個例外狀況處理模型之間的轉換,讓每個 C 例外狀況都與特定類別相關聯。 若要轉換其中一個,您可以定義 C 例外狀況「包裝函式」類別,以使用或衍生自,以便將特定類別類型屬性設為 C 例外狀況。 如此一來,每個 C 例外狀況都可以由特定的C++ catch 處理程式分開處理,而不是單一處理程式中的所有例外狀況。
您的包裝函式類別包含的介面可能會包括一些決定例外狀況值的成員函式,而且這些成員函式會存取 C 例外狀況模型所提供的延伸例外狀況內容資訊。 您也可以定義預設建構函式和接受 unsigned int 自變數的建構函式(以提供基礎 C 例外狀況表示法),以及位複製建構函式。 以下是 C 例外狀況包裝函式類別的可能實作:
// exceptions_Exception_Handling_Differences2.cpp
// compile with: /c
class SE_Exception {
private:
SE_Exception() {}
SE_Exception( SE_Exception& ) {}
unsigned int nSE;
public:
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() {
return nSE;
}
};
若要使用此類別,請在每次擲回 C 例外狀況時,安裝由內部例外狀況處理機制呼叫的自定義 C 例外狀況轉譯函式。 在您的轉譯函式中,您可以擲回任何類型例外狀況(可能是 SE_Exception 衍生自 SE_Exception的類型或類別類型),這些例外狀況可由適當的比對C++ catch 處理程序攔截。 轉譯函式可以改為傳回,這表示它未處理例外狀況。 如果轉譯函式本身引發 C 例外狀況, 則會呼叫 terminate 。
若要指定自定義翻譯函式,請使用翻譯函式的名稱作為其單一自變數來呼叫 _set_se_translator 函式。 您撰寫的轉譯函式會針對具有 try 區塊的堆疊上的每個函式調用呼叫一次。 沒有預設翻譯函式;如果您未藉由呼叫 _set_se_translator 來指定一個,C 例外狀況只能由省略號 catch 處理程序攔截。
範例 - 使用自定義翻譯函式
例如,下列程式碼會安裝自訂轉譯函式,然後引發由 SE_Exception 類別包裝的 C 例外狀況:
// exceptions_Exception_Handling_Differences3.cpp
// compile with: /EHa
#include <stdio.h>
#include <eh.h>
#include <windows.h>
class SE_Exception {
private:
SE_Exception() {}
unsigned int nSE;
public:
SE_Exception( SE_Exception& e) : nSE(e.nSE) {}
SE_Exception(unsigned int n) : nSE(n) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
void SEFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
printf_s( "In finally\n" );
}
}
void trans_func( unsigned int u, _EXCEPTION_POINTERS* pExp ) {
printf_s( "In trans_func.\n" );
throw SE_Exception( u );
}
int main() {
_set_se_translator( trans_func );
try {
SEFunc();
}
catch( SE_Exception e ) {
printf_s( "Caught a __try exception with SE_Exception.\n" );
printf_s( "nSE = 0x%x\n", e.getSeNumber() );
}
}
In trans_func.
In finally
Caught a __try exception with SE_Exception.
nSE = 0xc0000094