table des matières
Problèmes courants avec la gestion des exceptions
À quoi sert la gestion des exceptions?
Comment utiliser la gestion des exceptions?
Si une exception est levée, l'exécution se poursuivra-t-elle vers le bas?
Si une exception est levée, comment traiter les variables membres dans sa portée?
En résumé, quel est le flux d'exécution de la gestion des exceptions?
Comment passer une exception personnalisée?
Comment personnaliser la gestion des exceptions via l'héritage?
Trois devraient et trois ne devraient pas être lors de l'écriture de gestionnaires d'exceptions
Problèmes courants avec la gestion des exceptions
À quoi sert la gestion des exceptions?
En fait, la gestion des exceptions est implémentée à l'aide d'instructions try-catch et d'indicateurs de gestion d'exceptions. Try est utilisé pour intercepter les exceptions, et catch est utilisé pour intercepter les exceptions et les traiter en conséquence. Lorsque nous rencontrons des instructions anormales, try-catch peut être utilisé pour réaliser une reconnaissance anormale. Par exemple, nous demandons généralement de l'espace mémoire de manière dynamique avec new, mais que se passe-t-il si l'espace d'application est trop grand et que la mémoire de l'ordinateur n'est pas utilisée? Pour identifier avec précision ce type d'erreur, nous pouvons utiliser l'instruction try-catch pour y parvenir, voir la routine «Comment utiliser la gestion des exceptions?» Pour plus de détails.
Comment utiliser la gestion des exceptions?
Utilisé pour identifier des anomalies spécifiques:
#include <exception>
#include <iostream>
using namespace std;
int main()
{
try // 用于识别try{}语句块中的异常并且抛出异常
{
int Size;
cin >> Size;
int *ArrayPointer = new int[Size]; // 我输入-1,出现bad_alloc异常
delete[] ArrayPointer;
}
catch (bad_alloc& exp) // 被相应的catch语句捕获
{
cout << exp.what() << endl;
}
catch (exception& exp) // 用于捕获除bad_alloc之外的异常
{
cout << exp.what() << endl;
}
}
Si nous identifions toutes les anomalies, nous pouvons simplifier les étapes ci-dessus:
#include <exception>
#include <iostream>
using namespace std;
int main()
{
try
{
int Size;
cin >> Size;
int *ArrayPointer = new int[Size];
delete[] ArrayPointer;
}
catch (exception& exp)
{
cout << exp.what() << endl;
}
}
Si une exception est levée, l'exécution se poursuivra-t-elle vers le bas?
Exemple de code
#include <exception>
#include <iostream>
using namespace std;
int main()
{
try // 用于识别try{}语句块中的所有异常并且抛出异常
{
int Size;
cin >> Size;
int *ArrayPointer = new int[Size];
cout << "正在继续执行" << endl; // 不会继续向下执行,直接由catch捕获异常然后执行处理程序
delete[] ArrayPointer;
}
catch (bad_alloc& exp) // 用于捕获bad_alloc特定异常
{
cout << exp.what() << endl;
}
catch (exception& exp) // 用于捕获除bad_alloc之外的其他所有异常
{
cout << exp.what() << endl;
}
}
résultat de l'opération
Analyse des résultats
Nous voyons dans les résultats que lorsqu'une exception est levée, elle sera interceptée par catch et exécutée dans le gestionnaire d'exceptions catch.
Si une exception est levée, comment traiter les variables membres dans sa portée?
Exemple de code
#include <exception>
#include <iostream>
using namespace std;
struct Mumber_A
{
Mumber_A()
{
cout << "调用构造函数" << endl;
}
~Mumber_A()
{
cout << "调用析构函数" << endl;
}
};
void ExceptionShow()
{
Mumber_A Obj_A;
throw "出现异常";
}
int main()
{
try
{
ExceptionShow();
}
catch (const char* Obj)
{
cout << "异常处理" << endl;
}
cout << "主程序结束" << endl;
}
résultat de l'opération
Analyse des résultats
Nous pouvons voir à travers les résultats en cours d'exécution que lorsque le bloc d'instructions try {} lève une exception, la première chose à faire est de déconstruire tous les objets dans le bloc d'instructions try {}, puis de passer à la capture pour exécuter le gestionnaire d'exceptions.
D'après les résultats, lorsqu'une exception est levée, elle est immédiatement interceptée par catch et entre dans le gestionnaire d'exceptions catch.
En résumé, quel est le flux d'exécution de la gestion des exceptions?
Comment passer une exception personnalisée?
#include <iostream>
#include <exception>
using namespace std;
void ExceptionShow1()
{
throw "抛出异常";
}
void ExceptionShow2()
{
ExceptionShow1();
throw; // 继续抛出异常
}
int main()
{
try
{
ExceptionShow2 ();
}
catch (const char* exp) // 捕捉ExceptionShow2抛出的异常
{
cout << "异常处理程序" << endl;
}
}
Comment personnaliser la gestion des exceptions via l'héritage?
#include <iostream>
#include <exception>
#include <string>
using namespace std;
class CustomException : public exception
{
private:
string reason;
public:
CustomException(string reason)
{
this->reason = reason;
}
~CustomException()
{
cout << "调用CustomException的析构函数" << endl;
}
virtual const char* what() const noexcept // throw()与noexcept等价,表明:在这个函数作用域内不可以抛出任何异常
{
return reason.c_str(); // 重载虚函数时,子类与父类各方面都必须一样
}
};
double Division(double divisor,double dividend)
{
if (dividend == 0)
{
throw CustomException("除数为零");
}
return divisor / dividend;
}
int main()
{
try
{
cout << "结果为" << Division(8, 0) << endl;
}
catch (exception& exp) // 一定要用引用
{
cout << exp.what() << endl;
}
}
La meilleure façon de personnaliser la gestion des exceptions est d'hériter de l'exception, car cela peut garantir qu'un indicateur d'exception personnalisé est ajouté sur la base de la réutilisation de tous les indicateurs d'exception de l'exception.
Quels sont les avantages de la gestion des exceptions personnalisée?
Bien sûr, ce n'est pas nécessaire, mais cela vous permet de réutiliser tous les blocs catch () qui interceptent les exceptions std :: exception. Lorsque vous écrivez votre propre classe d'exception, vous ne pouvez hériter d'aucune classe, mais vous devez insérer une nouvelle instruction catch (MyNewExceptionType &) à tous les endroits appropriés.
Trois devraient et trois ne devraient pas être lors de l'écriture de gestionnaires d'exceptions