9.4. Hiérarchie des exceptions

Le mécanisme des exceptions du C++ se base sur le typage des objets, puisque le lancement d'une exception nécessite la construction d'un objet qui la caractérise, et le bloc catch destination de cette exception sera sélectionné en fonction du type de cet objet. Bien entendu, les objets utilisés pour lancer les exceptions peuvent contenir des informations concernant la nature des erreurs qui se produisent, mais il est également possible de classifier ces erreurs par catégories en se basant sur leurs types.

En effet, les objets exceptions peuvent être des instances de classes disposant de relations d'héritage. Comme les objets des classes dérivées peuvent être considérés comme des instances de leurs classes de base, les gestionnaires d'exception peuvent récupérer les exceptions de ces classes dérivées en récupérant un objet du type d'une de leurs classes de base. Ainsi, il est possible de classifier les différents cas d'erreurs en définissant une hiérarchie de classe d'exceptions, et d'écrire des traitements génériques en n'utilisant que les objets d'un certain niveau dans cette hiérarchie.

Le mécanisme des exceptions se montre donc plus puissant que toutes les autres méthodes de traitement d'erreurs à ce niveau, puisque la sélection du gestionnaire d'erreur est automatiquement réalisée par le langage. Cela peut être très pratique pour peu que l'on ait défini correctement sa hiérarchie de classes d'exceptions.

Exemple 9-4. Classification des exceptions

#include <iostream>

using namespace std;

// Classe de base de toutes les exceptions :
class ExRuntimeError
{
};

// Classe de base des exceptions pouvant se produire
// lors de manipulations de fichiers :
class ExFileError : public ExRuntimeError
{
};

// Classes des erreurs de manipulation des fichiers :
class ExInvalidName : public ExFileError
{
};

class ExEndOfFile : public ExFileError
{
};

class ExNoSpace : public ExFileError
{
};

class ExMediumFull : public ExNoSpace
{
};

class ExFileSizeMaxLimit : public ExNoSpace
{
};

// Fonction faisant un travail quelconque sur un fichier :
void WriteData(const char *szFileName)
{
    // Exemple d'erreur :
    if (szFileName == NULL) throw ExInvalidName();
    else
    {
        // Traitement de la fonction
        // etc.

        // Lancement d'une exception :
        throw ExMediumFull();
    }
}

void Save(const char *szFileName)
{
    try
    {
        WriteData(szFileName);
    }
    // Traitement d'un erreur spécifique :
    catch (ExInvalidName &)
    {
        cout << "Impossible de faire la sauvegarde" << endl;
    }
    // Traitement de toutes les autres erreurs en groupe :
    catch (ExFileError &)
    {
        cout << "Erreur d'entrée / sortie" << endl;
    }
}

int main(void)
{
    Save(NULL);
    Save("data.dat");
    return 0;
}

La librairie standard C++ définit elle-même un certain nombre d'exceptions standards, qui sont utilisées pour signaler les erreurs qui se produisent à l'exécution des programmes. Quelques-unes de ces exceptions ont déjà été présentées avec les fonctionnalités qui sont susceptibles de les lancer. Vous trouverez une liste complète des exceptions de la librairie standard du C++ dans la Section 13.2.