Différences de gestion des exceptions
La principale différence entre la gestion structurée des exceptions et la gestion des exceptions C++ est que le modèle de gestion des exceptions C++ s'occupe les types, alors que les cas de modèle de gestion structurée des exceptions C avec des exceptions d'un type - spécifiquement, unsigned int.Autrement dit, les exceptions C sont identifiées par une valeur entière non signé, alors que les exceptions C++ sont identifiées par le type de données.Lorsqu'une exception est levée dans C, chaque gestionnaire possible exécute un filtre qui examine le contexte d'exception C et détermine si recevoir l'exception, la passe à un autre gestionnaire, ou l'ignore.Lorsqu'une exception est levée en C++, elle peut être de tout type.
Une deuxième différence est que le modèle de gestion structurée des exceptions C sous le nom « asynchrone » en ce sens que les exceptions se produisent secondaire à l'ordre d'exécution normal.Le mécanisme de gestion des exceptions C++ est entièrement « synchrone, » qui signifie que les exceptions se produisent uniquement lorsqu'elles sont levées.
Si l'exception c est levée dans un programme C++, elle peut être gérée par un gestionnaire d'exceptions structuré avec son filtre associé ou par le gestionnaire catch C++, celui qui est dynamiquement plus proche du contexte d'exception.Par exemple, le programme C++ suivant déclenche l'exception c à l'intérieur de le contexte de test C++ :
Exemple
// 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;
}
}
Par exemple, le code suivant installe une fonction personnalisée de traduction, puis déclenche l'exception c qui sont encapsulées par la classe d' SE_Exception :
// 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() );
}
}
Classe wrapper d'exception C
Dans un exemple simple comme le ci-dessus, l'exception C peut être intercepté uniquement par un gestionnaire catch de sélection (...).aucune information sur le type ou la nature de l'exception n'est communiquée au gestionnaire.Bien que cette méthode fonctionne, vous devez parfois définir une transformation entre les deux modèles de gestion des exceptions afin que chaque exception C est associée à une classe spécifique.Pour ce faire, vous pouvez définir la classe de wrapper d'exception c, qui peut être utilisé ou dérivé pour attribuer un type spécifique de la classe à l'exception c.Ce faisant, chaque exception C peut être gérée par le gestionnaire catch C++ plus séparément que dans l'exemple précédent.
Votre classe wrapper peut avoir une interface qui se compose de certaines fonctions membres qui déterminent la valeur de l'exception, et qui accèdent aux informations de contexte étendues d'exception fournies par le modèle d'exception C.Vous pouvez également définir un constructeur par défaut et un constructeur qui accepte un argument d' unsigned int (pour assurer la représentation sous-jacente d'exception C), et un constructeur de copie de bits.Voici une implémentation possible de classe wrapper d'exception 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;
}
};
Pour utiliser cette classe, vous installez une fonction personnalisée de traduction d'exception C qui est appelée par l'exception interne c de mécanisme de gestion des exceptions chaque fois que est levée.Dans votre fonction de traduction, vous pouvez lever une exception typée (éventuellement un type d' SE_Exception , ou un type de classe dérivée d' SE_Exception) qui peut être interceptée par un gestionnaire catch approprié de la correspondance C++.La fonction de traduction peut simplement retourner une valeur, ce qui signifie qu'elle n'a pas géré l'exception.Si la fonction de traduction elle-même déclenche l'exception c, achevez -le est appelé.
Pour spécifier une fonction personnalisée de traduction, appelez la fonction de _set_se_translator avec le nom de la fonction de traduction comme unique argument.La fonction de traduction que vous entrez est appelée une fois pour chaque appel de fonction sur la pile qui a des blocs de test .Aucune fonction par défaut de traduction ; si vous ne spécifiez pas un en appelant _set_se_translator, l'exception C ne peut être interceptée par un gestionnaire catch de sélection.