Hiérarchies d’exceptions personnalisées
Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 82 sur 104.
Bien que la bibliothèque standard fournisse des classes d’exception utiles comme std::runtime_error, les applications du monde réel bénéficient souvent de la création de hiérarchies d’exceptions personnalisées. En définissant vos propres classes d’exception qui héritent des exceptions standard, vous pouvez créer des types d’erreur spécifiques au domaine qui fournissent un contexte supplémentaire et permettent une gestion des erreurs plus précise.
Une classe exception personnalisée hérite généralement de std::exception ou de l’une de ses classes dérivées et redéfinit la méthode what() :
#include <exception>
#include <string>
class DatabaseException : public std::exception {
std::string message;
public:
DatabaseException(const std::string& msg) : message(msg) {}
const char* what() const noexcept override { return message.c_str(); }
};
class ConnectionException : public DatabaseException {
public:
ConnectionException(const std::string& host)
: DatabaseException("Failed to connect to: " + host) {}
};
class QueryException : public DatabaseException {
public:
QueryException(const std::string& query)
: DatabaseException("Invalid query: " + query) {}
};Cette hiérarchie permet aux blocs catch de gérer les exceptions à différents niveaux de spécificité :
try {
// opérations de base de données...
throw ConnectionException("localhost");
} catch (const ConnectionException& e) {
std::cout << "Connection issue: " << e.what() << "\n";
} catch (const DatabaseException& e) {
std::cout << "Database error: " << e.what() << "\n";
} catch (const std::exception& e) {
std::cout << "General error: " << e.what() << "\n";
}Le spécificateur noexcept sur what() est important : il garantit que la méthode ne lèvera pas d’exception, ce qui est requis par l’interface de la classe base. Ordonnez vos blocs catch du plus spécifique au plus général, car C++ utilise le premier gestionnaire correspondant.
Défi
FacileConstruisons un système de traitement de fichiers avec une hiérarchie d’exceptions personnalisées qui gère différents types d’erreurs liées aux fichiers. Vous créerez des exceptions spécifiques au domaine qui héritent d’une classe d’exception de base, ce qui permettra une gestion précise des erreurs à différents niveaux de spécificité.
Vous organiserez votre code sur trois fichiers :
FileExceptions.h: définissez votre hiérarchie d’exceptions personnalisées pour les opérations sur les fichiers.Créez une classe de base
FileExceptionqui hérite destd::exception. Elle doit stocker un message d’erreur et redéfinir la méthodewhat()avec le spécificateurnoexcept.Créez ensuite deux classes d’exceptions dérivées :
FileNotFoundException: reçoit un nom de fichier et crée le message suivant :File not found: [filename]PermissionDeniedException: reçoit un nom de fichier et crée le message suivant :Permission denied: [filename]
Chaque classe dérivée doit appeler le constructeur de sa classe parente avec le message approprié.
FileProcessor.h: définissez une classeFileProcessorqui simule des opérations sur les fichiers et lève vos exceptions personnalisées.Votre
FileProcessordoit avoir une méthodeopenFile(const std::string& filename)qui simule l’ouverture d’un fichier :- Si le nom de fichier contient
missing, levez uneFileNotFoundException - Si le nom de fichier contient
locked, levez unePermissionDeniedException - Sinon, renvoyez la chaîne
Successfully opened: [filename]
- Si le nom de fichier contient
main.cpp: lisez un seul nom de fichier depuis l’entrée.Créez un
FileProcessoret essayez d’ouvrir le fichier. Utilisez un bloc try-catch avec des gestionnaires classés du plus spécifique au plus général :- Interceptez
FileNotFoundExceptionet affichez :File Error: [message] - Interceptez
PermissionDeniedExceptionet affichez :Access Error: [message] - Interceptez
FileExceptionet affichez :General File Error: [message]
Si aucune exception n’est levée, affichez le message de réussite renvoyé par
openFile().- Interceptez
Par exemple, avec l’entrée report.txt :
Successfully opened: report.txtAvec l’entrée missing_data.csv :
File Error: File not found: missing_data.csvAvec l’entrée locked_config.ini :
Access Error: Permission denied: locked_config.iniCe défi montre comment les hiérarchies d’exceptions personnalisées vous permettent de gérer les erreurs avec le niveau de détail approprié : intercepter des exceptions spécifiques lorsque vous avez besoin d’une gestion précise, ou intercepter l’exception de base lorsque vous souhaitez gérer toutes les erreurs de fichier de manière uniforme.
Essayez vous-même
#include <iostream>
#include <string>
#include "FileExceptions.h"
#include "FileProcessor.h"
using namespace std;
int main() {
string filename;
cin >> filename;
FileProcessor processor;
// TODO: Utilisez un bloc try-catch pour gérer les exceptions
// Ordonnez les gestionnaires du plus spécifique au plus général :
// 1. Attrapez FileNotFoundException - affichez : "File Error: [message]"
// 2. Attrapez PermissionDeniedException - affichez : "Access Error: [message]"
// 3. Attrapez FileException - affichez : "General File Error: [message]"
// S'il n'y a pas d'exception, affichez le message de succès de openFile()
try {
// TODO: Appelez processor.openFile() et gérez le résultat
}
// TODO: Ajoutez les blocs catch dans l'ordre du plus spécifique au plus général
return 0;
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesGénération et compilation en C++Fichiers d’en-tête et fichiers sourceEspaces de noms et portéeIntroduction à la POO en C++Classes et objetsLe pointeur « this »Méthodes (fonctions membres)Attributs (membres de données)Bases des constructeurs et destructeursRécapitulatif - Calculatrice simple4Propriétés de classe
Membres d’instance et statiquesAccesseurs et mutateursFonctions membres constMot-clé mutableMéthodes et variables statiquesFonctions et classes amiesRécapitulatif - Gestionnaire de compte bancaire7Héritage
Héritage de baseNiveaux d’accès de l’héritageOrdre d’appel des constructeurs et destructeursRedéfinition des méthodesFonctions virtuelles et VTableHéritage multipleHéritage virtuelRécapitulatif : hiérarchie des employés10Vue d’ensemble de la STL
Vue d’ensemble et philosophie de la STLConteneurs de la STLItérateursAlgorithmes de la STLFoncteurs et expressions lambdaRécapitulatif - fréquence des mots13Modèles de conception, partie 1
Introduction aux modèles de conceptionModèle SingletonFabrique et fabrique abstraiteModèle BuilderModèle ObserverModèle Strategy2Gestion de la mémoire
Mémoire de pile ou de tasPointeurs et référencesMémoire dynamique (new/delete)Pointeurs intelligents en C++RAII en C++Récapitulatif - Gestionnaire de tableaux dynamiques5Encapsulation
Spécificateurs d’accès en C++Spécificateurs d’accès en profondeurMasquage de l’informationStruct vs classeClasses imbriquées et internesRécapitulatif - Système de gestion des dossiers étudiants8Polymorphisme
Polymorphisme à la compilation vs à l’exécutionSurcharge de fonctionsRetour sur les fonctions virtuellesFonctions virtuelles puresClasses abstraitesConception d’interfaces en C++Conversion dynamique et RTTIRécapitulatif - Calculateur de formes11Concepts avancés de la POO
Composition ou héritageMixins via CRTPIdiom PimplEffacement de typeClasses enum et typage fortGestion des exceptions en POOHiérarchies d’exceptions personnalisées3Constructeurs et destructeurs
Constructeur par défautConstructeur paramétréConstructeur de copieConstructeur de déplacementListes d’initialisation des constructeursConstructeurs déléguésApprofondissement des destructeursRègle des trois / cinq / zéroRécapitulatif - Classe String6Surcharge des opérateurs
Introduction à la surcharge des opérateursSurcharge des opérateurs arithmétiquesSurcharge des opérateurs de comparaisonOpérateurs de fluxSurcharge de l’opérateur d’affectationSurcharge des opérateurs [] et ()Opérateurs de conversion de typeRécapitulatif – Classe Matrix9Templates
Templates de fonctionsTemplates de classesSpécialisation des templatesTemplates variadiquesBases de SFINAE et des traits de typesRécapitulatif - Conteneur génériqueEntraînez-vous par vous-même : Compilateur C++ en ligne