TUTORIAL: C + + exceptions

  • spork
  • Brewmaster
  • Silver Member
  • Avatar de l’utilisateur
  • Inscription: Sep 22, 2003
  • Messages: 6128
  • Loc: Seattle, WA
  • Status: Offline

Message Mars 19th, 2008, 10:52 pm

Introduction


Note: Ce tutoriel suppose une connaissance de base du langage C + +. Vous devriez savoir comment utiliser des fonctions, des variables et avoir une connaissance élémentaire de la façon dont les catégories de travail.

Note: Le code source complet pour les exemples de ce tutoriel peut être téléchargée à la fin du tutoriel.

Dans ce didacticiel, nous aborderons les rudiments de la gestion des exceptions en C + +. Eh bien toucher aussi sur comment créer et utiliser vos propres exceptions dans vos applications, ainsi que la façon de traiter les exceptions levées par la STL (Standard Template Library) classes.


Quick Reference


Ceci est pour les gens qui sont déjà familiarisés à l'exception dans l'objet d'autres langages orientés et ont simplement besoin de connaître la syntaxe pour utiliser des exceptions en C + +. Si vous remplissez ce tutoriel, s'il vous plaît passez à la section suivante, «Qu'est-ce qu'une exception?

Lancer une exception:
CPP Code: [ Select ]
void someFunction() throw( int, MyException ) {
    throw 5;
    // or
    throw MyException();
}
  1. void someFunction() throw( int, MyException ) {
  2.     throw 5;
  3.     // or
  4.     throw MyException();
  5. }


La capture d'exceptions:
CPP Code: [ Select ]
try {
    someFunction();
}
catch( int ie ) {
    cout << "Caught an int: " << e << endl;
}
catch( MyException& me ) {
    cout << "Exception: " << me.getMessage() << endl;
}
catch( ... ) {
    cout << "Caught an unknown exception." << endl;
}
  1. try {
  2.     someFunction();
  3. }
  4. catch( int ie ) {
  5.     cout << "Caught an int: " << e << endl;
  6. }
  7. catch( MyException& me ) {
  8.     cout << "Exception: " << me.getMessage() << endl;
  9. }
  10. catch( ... ) {
  11.     cout << "Caught an unknown exception." << endl;
  12. }


Rethrowing une exception:
CPP Code: [ Select ]
try {
    someFunction();
}
catch( MyException& me ) {
    rethrow me;
}
catch( ... ) {
    rethrow;
}
  1. try {
  2.     someFunction();
  3. }
  4. catch( MyException& me ) {
  5.     rethrow me;
  6. }
  7. catch( ... ) {
  8.     rethrow;
  9. }



Qu'est-ce une exception?


Une exception est une valeur qui est lancée par une partie d'un programme quand une situation exceptionnelle se produit. Normalement, les exceptions sont utilisées pour indiquer qu'un inattendue, mais planifiée pour, une erreur s'est produite et devrait être traitée par une autre partie du programme.

Par exemple, une prise réseau pourrait être le maintien d'une connexion à un hôte distant, lorsque la connexion est interrompue de manière inattendue. Le programme, bien sûr, doit continuer à fonctionner, mais elle doit composer avec le fait que le socket n'est plus utilisable. La socket peut lancer une exception, qui sera capturé par un plus-part de levier du programme, qui portera sur la situation de manière appropriée, par exemple, en créant un nouveau socket ou avertir l'utilisateur.

L'une certaine terminologie commune impliqués avec les exceptions qui vous devriez vous familiariser avec. Jetons un regard sur les trois plus courantes C + + mots-clés utilisés avec des exceptions:

essayer - Nous utilisons un bloc try pour entourer des parties de code qui peut générer des exceptions. Cette section de code est spécialement étudié lors de l'exécution à voir d'éventuelles exceptions qui mai ont été jetés par des appels à des fonctions au sein du bloc try.

attraper - Chaque bloc try n'ont généralement qu'un seul ou plusieurs blocs catch suivent. Un bloc de capture contient le code qui doit être exécuté chaque fois qu'une exception d'un type particulier est pris. Cela nous permet de personnaliser le comportement de notre programme en fonction de quels genres de choses peuvent mal tourner.

jeter - Ce mot clé sert à deux fins. Lorsqu'ils sont utilisés dans le corps d'une fonction, il est utilisé pour lancer une exception, en lui passant la pile des appels. Lorsqu'ils sont utilisés dans l'en-tête d'une fonction, il est utilisé pour spécifier les types d'exceptions de la fonction mai jeter.

rethrow - Nous utilisons ce à prendre une exception que nous avons pris dans un bloc catch et de le jeter la pile des appels. Il est normalement utilisé lorsque la fonction ne possède pas la capacité de traiter l'exception et doit passer sur l'exception de la fonction suivante sur la pile.

Une description complète de ce que la pile est et comment il fonctionne est en dehors du champ d'application de ce tutoriel. Pour faciliter ce tutorial, cependant, Ill décrire brièvement le concept.

En un mot, toute fonction qui est appelée en C + + a toutes ses variables locales et les informations mis une aire a spéciales de la mémoire appelée la pile. Comme vous l'aurez deviné, les données dans ce domaine sont ajoutés et supprimés de la même façon que les choses sont retirés vers et à partir d'une pile ordinaire structure des données. Chaque fois qu'une fonction est appelée, elle est placée sur la pile. Une fois la fonction retourne, il est retiré de la pile. Main () sera toujours la première fonction ajoutée à la pile et le dernier enlevés.

Quand une exception est levée par la fonction actuelle, il est passé à la fonction suivante sur la pile. Cette fonction doit faire face à l'exception, soit par gracieusement à leur manipulation par un bloc catch, ou en le faisant passer la pile des appels à sa fonction d'appel. Dans le cas de la deuxième situation, l'exception va continuer à propager la pile jusqu'à ce qu'elle atteigne une fonction qui peut succès de capture et de traiter l'exception. Si aucune fonction gère l'exception, elle arrivera à main (). Si main () ne capturent pas et de faire face à l'exception, le programme se termine.


Throwing exceptions


Maintenant que vous savez ce qu'est une exception est, laisse le regard à la manière de lever des exceptions dans nos propres fonctions. Jetez un oeil à l'exemple suivant:

CPP Code: [ Select ]
void doSomething() {
   
    throw std::string( "Error: something went wrong" );
}
  1. void doSomething() {
  2.    
  3.     throw std::string( "Error: something went wrong" );
  4. }


Cette fonction simple, doSomething () , Est juste inutile maintenant, mais il sert comme un exemple de base de la façon de lancer une exception. Notez que la jeter mot clé est utilisé pour lancer effectivement l'exception. À ce stade, l'exécution du programme s'arrête à cette ligne, et l'exception sera levée en place la pile d'appel à quelque fonction invoquée doSomething () . Il appartient alors à cette fonction pour faire face à l'exception, que nous verrons bientôt.

Un autre point important à prendre note de l'objet est d'être levée. Dans cet exemple, nous jetons une chaîne comme notre exception. Mais nous ne sommes pas limités à cela: en fait, vous pouvez jeter les données de pratiquement n'importe quel type comme une exception. Certains types fonctionnent beaucoup mieux que d'autres, et en un instant regardez bien les avantages et les inconvénients de l'utilisation de divers types comme des exceptions.

Maintenant, il faudra évidemment jamais écrire une fonction comme celle ci-dessus, laisse donc envisager une utilisation un peu plus plausible de lancer une exception:

CPP Code: [ Select ]
float squareRoot( float num ) {
   
    float result = 0;
   
    if( num < 0 ) {
        throw std::string(
            "Error: number must not be negative" );
    }
   
    result = sqrt( num );
   
    return result;
}
  1. float squareRoot( float num ) {
  2.    
  3.     float result = 0;
  4.    
  5.     if( num < 0 ) {
  6.         throw std::string(
  7.             "Error: number must not be negative" );
  8.     }
  9.    
  10.     result = sqrt( num );
  11.    
  12.     return result;
  13. }


Cette fonction, squareRoot , Prend un nombre à virgule flottante et renvoie la racine carrée de sa création.

Note: sqrt () est une fonction trouvée dans la bibliothèque mathématique C, et peuvent être utilisés en incluant l'en-tête <cmath>.

Maintenant, puisque nous ne pouvons pas calculer la racine carrée d'un nombre négatif, on doit lever une exception si un nombre négatif est passé dans la fonction. Dans ce cas, nous lançons une chaîne à nouveau afin que nous puissions utiliser l'exception comme un message d'erreur.

Notez que nous n'avons pas besoin de mettre le calcul proprement dit, resultat = sqrt (num); , Dans un else if bloc. En effet, si le nombre est négatif, l'exception sera levée, et d'exécution dans la fonction s'arrête. La seule exception sera levée, et à l'exécution du programme seront transférés à la fonction d'appel pour traiter l'exception.


Que peut-on jeté?


Comme je l'ai mentionné plus tôt, pratiquement n'importe quel type de données en C + + peut être jeté comme une exception. Par exemple, nous pourrions tout aussi bien pu jeter un entier dans nos doSomething () Par exemple:

CPP Code: [ Select ]
void doSomething() {
   
    throw 5;
}
  1. void doSomething() {
  2.    
  3.     throw 5;
  4. }


Ou, nous pourrions avoir jeté, par exemple, une valeur booléenne:

CPP Code: [ Select ]
void doSomething() {
   
    bool someVariable = false;
    throw someVariable;
}
  1. void doSomething() {
  2.    
  3.     bool someVariable = false;
  4.     throw someVariable;
  5. }


Ce sont les deux tout aussi valables et exécutera parfaitement. Mais le problème avec l'utilisation de types de données primitifs comme des exceptions, c'est qu'ils fournissent peu d'information sur ce qu'est l'erreur effectivement produite. Quand on jette une exception, il est utile d'être en mesure d'inclure des informations sur ce qui s'est passé réellement dans notre application: le contexte, l'État, des informations supplémentaires, et ainsi de suite.

Même les chaînes de lancer (C-style ou STL, peu importe) n'est pas la meilleure solution. L'exception idéal serait de pouvoir contenir toutes sortes d'informations que nous précisions sans nous limiter à la structure linéaire d'une chaîne. Alors, que faisons-nous pas normalement? Créer une classe .

Rappelez-vous, n'importe quel type de données en C + + peut être jeté comme une exception, et cela inclut tous les types de données personnalisées que nous créons. Par conséquent, nous pouvons créer des classes pour représenter nos exceptions, et ces classes peut contenir autant ou aussi peu d'information que nous aimons, structuré toutefois que nous aimons.

Jetons un oeil à une classe d'exception simple, CustomException, que fait la démonstration:

CPP Code: [ Select ]
class CustomException {
 
private:
   
    std::string message;
 
public:
    CustomException( std::string message );
    inline std::string getMessage() { return message; };
 
};
  1. class CustomException {
  2.  
  3. private:
  4.    
  5.     std::string message;
  6.  
  7. public:
  8.     CustomException( std::string message );
  9.     inline std::string getMessage() { return message; };
  10.  
  11. };


Ici, nous avons déclaré une classe simple, CustomException. La classe a un membre de données, Message , Qui tiendra le message d'erreur associée à notre exception. Nous définissons un constructeur de base qui prend une chaîne comme argument pour définir le message, et nous disposons d'un accès pour Message . Maintenant, on peut jeter une instance de notre classe CustomException comme une exception, comme ceci:

CPP Code: [ Select ]
void doSomething() {
   
    throw CustomException( "An error occurred." );
}
  1. void doSomething() {
  2.    
  3.     throw CustomException( "An error occurred." );
  4. }


Au début, cela ne semble pas plus utile que de lancer une chaîne de familles monoparentales. Heck, il exige même d'écrire plus de code juste pour créer la classe! Mais regardez le concept nouveau. Maintenant que notre exception est représentée comme un objet entier de notre classe plutôt que d'une primitive ou une chaîne, nous pouvons ajouter des tas d'informations à notre exception en ajoutant des données membres de notre classe. Par exemple, permet d'ajouter quelques morceaux plus d'informations pour notre classe:

Code: [ Select ]
class CustomException {
 
private:
   
    std::string message;
    int errorCode;
    bool fatal;

 
public:
    CustomException( std::string message );
    inline std::string getMessage() { return message; };
    inline int getErrorCode() { return errorCode; };
    inline bool isFatal() { return fatal; };

 
};
  1. class CustomException {
  2.  
  3. private:
  4.    
  5.     std::string message;
  6.     int errorCode;
  7.     bool fatal;
  8.  
  9. public:
  10.     CustomException( std::string message );
  11.     inline std::string getMessage() { return message; };
  12.     inline int getErrorCode() { return errorCode; };
  13.     inline bool isFatal() { return fatal; };
  14.  
  15. };


Maintenant que weve ajouté des données supplémentaires sur les conditions et les circonstances entourant le problème qui a généré l'exception, quelle que soit la fonction finit par la manipulation la fonction sera mieux en mesure de s'en occuper correctement.

L'approche de conception commun pour les classes d'exceptions est de définir une classe d'exception de base qui détient des informations très élémentaires sur une classe. Nous pourrions alors créer des sous-classes pour différents types d'exception, avec chaque sous-classe contenant des informations spécifiques relatives à chaque exception particulière.

Par exemple, supposons que nous voulions créer un nouveau type d'exception, FileNotFoundException, de traiter des fichiers I / O. On peut simplement étendre notre classe CustomException et ajouter des informations pertinentes:

Code: [ Select ]
class FileNotFoundException : public CustomException {
 
private:
   
    std::string filename;
 
public:
    FileNotFoundException( std::string filename );
    inline std::string getFilename() { return filename; };

   
    // Override the getMessage() method
    inline std::string getMessage() {
        std::stringstream ss;
        ss << "File not found: " << filename;
        return ss.str();
    }

   
    // note: all other member data and methods are inherited!
};
  1. class FileNotFoundException : public CustomException {
  2.  
  3. private:
  4.    
  5.     std::string filename;
  6.  
  7. public:
  8.     FileNotFoundException( std::string filename );
  9.     inline std::string getFilename() { return filename; };
  10.    
  11.     // Override the getMessage() method
  12.     inline std::string getMessage() {
  13.         std::stringstream ss;
  14.         ss << "File not found: " << filename;
  15.         return ss.str();
  16.     }
  17.    
  18.     // note: all other member data and methods are inherited!
  19. };


Maintenant, nous pouvons jeter un FileNotFoundException si nous courons vers une situation où il nous est impossible d'ouvrir un fichier en lecture ou en écriture. Au lieu de l'initialisation de l'exception avec un message, elle passe bien le nom du fichier qui n'ont pas pu être ouvert, et chaque fois que nous appelons getMessage () , Notre version substituée affichera "Fichier non trouvé:" et le nom de fichier. Neat!


Utilisation de blocs try / catch pour gérer les exceptions


Maintenant que les exceptions étaient à l'aise de jet, permet de jeter un oeil à la façon d'intercepter et de gérer une exception qui a été levée.

En C + +, nous utilisons un essayer bloc d'entourer le code qui a la capacité de lever des exceptions. Code au sein essayer bloque complètement de fonctionner normalement au titre des autres circonstances exceptionnelles.

Code: [ Select ]
try {
    std::cout << "Calling a function that may throw an exception..."
        << std::endl;
    doSomething();  // may throw an exception
}
  1. try {
  2.     std::cout << "Calling a function that may throw an exception..."
  3.         << std::endl;
  4.     doSomething();  // may throw an exception
  5. }


Cependant, une fois qu'une exception est levée par un appel à une fonction au sein du bloc, l'exécution s'arrête à cette ligne dans le bloc et est remis à essayer s partenaires, le attraper bloc. Ajoutons-en une attraper bloc que les captures d'objets CustomException que mai ont été jetés par doSomething () :

Code: [ Select ]
try {
    std::cout << "Calling a function that may throw an exception..."
        << std::endl;
    doSomething();  // may throw an exception
}
catch( CustomException e ) {
   
    std::cout << "Exception: " << e.getMessage();
}

  1. try {
  2.     std::cout << "Calling a function that may throw an exception..."
  3.         << std::endl;
  4.     doSomething();  // may throw an exception
  5. }
  6. catch( CustomException e ) {
  7.    
  8.     std::cout << "Exception: " << e.getMessage();
  9. }


Remarquez comment l'exception est transféré au bloc de capture et peut être consulté via la variable CustomException e . (J'ai choisi de nommer la variable e , Mais vous mai choisir n'importe quel nom légal vous le désirez, exactement comme avec la fonction arguments). Maintenant, nous pouvons accéder aux informations nécessaires contenues dans l'exception, et exécuter du code appropriée en fonction de cette information.

Catching en valeur par rapport à la capture par référence


Maintenant, le code ci-dessus va compiler et travailler, mais theres un problème. Chaque fois que nous intercepter des exceptions dans la manière dont a vu plus haut, nous sommes capture par valeur . Ce concept a un rapport direct avec le passage d'arguments aux fonctions par valeur. Catching the exception en valeur signifie que chaque fois que l'exception est passée à la pile des appels, une copie de l'exception est faite et envoyé à la fonction suivante. Cela conduit à la fois une réduction de l'efficacité (grandes, complexes classes exceptions mai être très complexes et prennent plus de temps pour copier) et un gaspillage de ressources (mémoire).

Alors, quelle est la solution? Comme vous l'aurez deviné, nous ne pouvons intercepter l'exception par référence plutôt que par valeur. Le changement dans la syntaxe devrait être très familier à toute personne qui est utilisé pour passer les arguments de fonction par référence:

Code: [ Select ]
try {
    std::cout << "Calling a function that may throw an exception..."
        << std::endl;
    doSomething();  // may throw an exception
}
catch( CustomException& e ) {
   
    std::cout << "Exception: " << e.getMessage();
}
  1. try {
  2.     std::cout << "Calling a function that may throw an exception..."
  3.         << std::endl;
  4.     doSomething();  // may throw an exception
  5. }
  6. catch( CustomException& e ) {
  7.    
  8.     std::cout << "Exception: " << e.getMessage();
  9. }


Remarquez le changement: e est déclaré comme une référence à un CustomException lieu d'une variable CustomException régulière.

En plus de performance et de gestion des ressources, la principale raison pour intercepter des exceptions en fonction est d'éviter données tranchage . Tranchage de données se produit lorsqu'un objet d'une certaine classe est copié dans un objet de l'un de ses super-classes. Lorsque cela arrive, toute donnée et un comportement spécifique à la sous-classe est «en tranches» au large, toute seules les données de la superclasse est préservée.

CPP Code: [ Select ]
try {
   
    // Assume that FileNotFoundException is a subclass
    // of CustomException
    throw FileNotFoundException( "example.txt" );
   
}
catch( CustomException e ) {
   
    std::cout << "Exception: " << e.getMessage();
}
  1. try {
  2.    
  3.     // Assume that FileNotFoundException is a subclass
  4.     // of CustomException
  5.     throw FileNotFoundException( "example.txt" );
  6.    
  7. }
  8. catch( CustomException e ) {
  9.    
  10.     std::cout << "Exception: " << e.getMessage();
  11. }


Prenons le code ci-dessus. Quel serait le résultat généré par le bloc catch dans ce cas? Idéalement, il serait d'imprimer "Fichier non trouvé:", suivi du nom de fichier, comme spécifié dans FileNotFoundException.getMessage (). Mais ce n'est pas le cas! Le problème est que toutes les données spécifiques à FileNotFoundException, tels que le membre de données de fichier, va être tranchée pour que l'objet s'inscrit dans e, a CustomException.

Pour éviter cela, nous saisissons l'exception par référence, qui fera en sorte que toutes les informations d'origine est conservée dans l'exception. Nous pourrons alors jeter la référence à une référence FileNotFoundException, et accéder à tous les membres appropriés, y compris la version correcte du getMessage ().


Catching...


Nous savons déjà que nous pouvons spécifier différentes de nombreuses attraper blocs pour gérer les exceptions de divers types. Mais que faire si une exception se pose que nous ne sommes pas prêts à prendre? Cela peut provoquer toutes sortes de comportements undersired à nos programmes. Dans l'idéal, se marier, comme pour s'assurer que nous couvrons toutes les bases , Y compris les exceptions que nous mai n'a pas été accepté. Pour ce faire, nous utilisons une syntaxe spéciale pour intercepter toutes les exceptions restants pour lesquels une entreprise existante attraper bloc n'a pas été précisée: le "..." Symbole.

Code: [ Select ]
try{
    doSomething();
}
catch( CustomException& ce ) {
    std::cout << "Exception: " << ce.getMessage();
}
catch( ... ) {
    std::cout << "An unknown exception was caught!";
}

  1. try{
  2.     doSomething();
  3. }
  4. catch( CustomException& ce ) {
  5.     std::cout << "Exception: " << ce.getMessage();
  6. }
  7. catch( ... ) {
  8.     std::cout << "An unknown exception was caught!";
  9. }


La syntaxe est très simple. Au lieu de spécifier le type d'exception à attraper, nous ellipses utilisation simple (...) Pour indiquer que ce bloc de capture doit rien prendre levée qui n'a pas été manipulé par un bloc catch précédente. Pour cette raison, nous avons presque toujours mettre la capture (...) Bloc à la fin de toutes les autres, pour s'assurer que toutes les exceptions sont prises en compte.

Notez que nous n'avons aucun moyen d'accéder à l'exception qui est capturé par ce bloc. Il n'existe aucun moyen pour obtenir sa valeur (s) ou de la manipuler.


Rethrowing une exception


Il existe de nombreuses fois quand une fonction mai intercepter une exception, mais est incapable d'y faire face de manière appropriée. Dans ce cas, nous voulons habituellement à passer l'exception de la pile des appels à la fonction immédiatement supérieure à y faire face. Nous passons sur cette exception, ou rethrow l'exception, en utilisant le rethrow Mot-clé:

Code: [ Select ]
try{
    doSomething();
}
catch( CustomException& ce ) {
    std::cout << "Exception: " << ce.getMessage();
    rethrow ce;
}
catch( ... ) {
    std::cout << "An unknown exception was caught!";
    rethrow;
}
  1. try{
  2.     doSomething();
  3. }
  4. catch( CustomException& ce ) {
  5.     std::cout << "Exception: " << ce.getMessage();
  6.     rethrow ce;
  7. }
  8. catch( ... ) {
  9.     std::cout << "An unknown exception was caught!";
  10.     rethrow;
  11. }


La syntaxe de rethrow est très simple. Dans le cas où nous en sommes récupération d'une exception d'un type connu, nous rethrow simplement l'objet qui a été capturé, indiqué par la variable utilisée par le bloc catch. De même, dans le cas où une exception d'un type inconnu est capturé au moyen de (...), Nous disons simplement rethrow . Cela devrait donner un sens puisque nous ne disposons pas d'accès direct à l'objet dans ce cas. Mais ne vous inquiétez pas, le compilateur sait mieux, et l'exception est relancée correctement.


Faire des promesses (et leur conservation!)



Je l'ai mentionné plus tôt dans ce tutoriel que le jeter mot-clé a deux usages. Weve vu l'un d'entre eux: pour lancer une exception dans une fonction. Jetons maintenant un coup d'oeil à cet autre usage.

Lorsque nous utilisons le jeter mot-clé dans l'en-tête d'une fonction, elle indique quel type d'exceptions que la fonction mai jeter. Ainsi, tout type qui ne figurent pas dans le throw () fait partie de l'en-tête ne peut pas et ne sera pas levée par cette fonction. Cela s'appelle un garantie . Essentiellement, vous faites une promesse à tous ceux qui utilisent votre fonction qu'il existe une liste fixe de types d'exception que votre fonction mai lancer, et que ce sont les seuls types qui doivent être visionnées à l'essayer blocs contenant votre fonction.

Permet de revoir notre fonction simple, doSomething () , D'inscrire cette information:

Code: [ Select ]
void doSomething(int value) throw( int, CustomException ) {
   
    if( value > 5 ) {
        throw CustomException( "An error occurred." );
    }
    else {
        throw 18;
    }
}
  1. void doSomething(int value) throw( int, CustomException ) {
  2.    
  3.     if( value > 5 ) {
  4.         throw CustomException( "An error occurred." );
  5.     }
  6.     else {
  7.         throw 18;
  8.     }
  9. }


Nous voyons ici que doSomething () est déclaré être en mesure de lancer deux types d'exceptions: entiers et CustomExceptions. D'autres fonctions qui appellent cette fonction désormais besoin que d'écrire les blocs catch pour ces deux types de données, et rien de plus. doSomething () est positif que si elle lève une exception, il sera toujours d'un de ces deux types.

Remarque: une fonction peut lever une exception de tout type de celles énumérées dans le throw () clause de la tête de la fonction, et aucune sous-classe de ces types.

Maintenant passons à regarder la trois niveaux de garanties exception, ou la sécurité exception, qu'une fonction peut avoir:

La faiblesse de garantie
Si la fonction lève une exception près, aucune fuite de ressources en conséquence.

Forte de garantie
Si la fonction renvoie une exception, aucune ressource n'est divulgué et les programmes de l'État demeure inchangé par rapport à ce qu'elle était avant l'opération.


Les garanties fonction qu'aucune exception ne sera levée d'elle, et que cette opération réussira toujours en toutes circonstances.

Bien sûr, comme la mer pour être en mesure de ne pas avoir à course garanties pour l'ensemble de nos fonctions, mais, objectivement, ce n'est tout simplement pas possible dans la plupart des systèmes. Bien qu'elle soit la meilleure garantie d'avoir, il est souvent très difficile à réaliser.

Permet de revoir notre fonction simple, doSomething () , Une dernière fois pour lui donner un no-throw garantie:

Code: [ Select ]
void doSomething(int value) throw() {
   
    value = 0;
}
  1. void doSomething(int value) throw() {
  2.    
  3.     value = 0;
  4. }


Notez que pour assurer un no-throw garantie, nous utilisons un vide throw () clause indiquant que cette fonction ne peut pas et ne sera pas jeter n'importe quel type d'exception.


STL exceptions


Le [acronyme = Standard Template Library: 3618k50i] STL [/acronym] contient une classe d'exception, std:: exception , Qui sert de la classe de base pour toutes les exceptions levées par les classes de la STL et fonctions. Semblable à notre getMessage () méthode dans notre classe CustomException propres, la classe d'exception STL contient une méthode appelée ce que () qui peuvent être utilisés pour obtenir le message d'erreur associée à l'exception. Lors de l'utilisation des classes STL, c'est souvent une bonne idée d'attraper cette exception dans le cas de quelque chose tourne mal:

Code: [ Select ]
try {
    std::cout << "cout is a std::ostream object and could throw an exception";
}
catch( std::exception& ex ) {
    std::cerr << "Exception: " << ex.what();
}

  1. try {
  2.     std::cout << "cout is a std::ostream object and could throw an exception";
  3. }
  4. catch( std::exception& ex ) {
  5.     std::cerr << "Exception: " << ex.what();
  6. }


En outre, nous pouvons modifier notre classe CustomException propres à étendre la classe d'exception STL, et donc l'utilisation du bloc catch même de rattraper toutes les exceptions dérivées de notre aussi. Ill laisser cet exercice à vous pendant que vous jouez avec vos histoires de nouvelles connaissances sur les exceptions.


Conclusion


Vous devriez maintenant avoir une solide compréhension de la façon de mettre en œuvre et utiliser les exceptions en C + +. Vous devez comprendre les concepts de lancer, attraper, et les exceptions rethrowing, ainsi que les différentes garanties que les fonctions peuvent faire au sujet des exceptions.

J'ai toujours les bienvenus questions ou des commentaires sur ce tutoriel. Il suffit de poster une réponse ou PM moi, im glad to help!
Attachments:
Exceptions.zip

(1.73 Kio) Téléchargé 778 fois

Complete source code for various examples using exceptions, including the CustomException class.

The Beer Monocle. Classy.
  • Anonymous
  • Bot
  • No Avatar
  • Inscription: 25 Feb 2008
  • Messages: ?
  • Loc: Ozzuland
  • Status: Online

Message Mars 19th, 2008, 10:52 pm

Afficher de l'information

  • Total des messages de ce sujet: 1 message
  • Modérateur: Tutorial Writers
  • Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 2 invités
  • Vous ne pouvez pas poster de nouveaux sujets
  • Vous ne pouvez pas répondre aux sujets
  • Vous ne pouvez pas éditer vos messages
  • Vous ne pouvez pas supprimer vos messages
  • Vous ne pouvez pas joindre des fichiers
 
 

© 2011 Unmelted, LLC. Ozzu® est une marque déposée de Unmelted, LLC