IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Exception non interceptée


Sujet :

C++

  1. #1
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut Exception non interceptée
    Bonjour,

    J'ai ceci et l'exception générée "TEST" n'est pas interceptée et je ne comprends pas pourquoi. Vos lumières seraient le bienvenues.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
       class Exception : public std::exception
       {
          public :
          std::string Message;
          explicit Exception(std::string const& Mes) throw() : Message(Mes) { }
          explicit Exception(const char *Mes) throw()          : Message(Mes) { }
          virtual const char* what() const throw()       {   return(exception::what());   }
          virtual ~Exception() throw() { }
       };
     
       int main() {
         try {
           throw std::logic_error("TEST");   // n'est pas interceptée dans le catch
           throw Exception("TEST2");  // est bien interceptée dans le catch
        } catch (Exception &e) {
          printf("%s\n",e.massage.c_str();
          retrun(1);
        }
        retrun(0);
      }

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    std::logic_error est une std::exception, elle peut être interceptée par catch ( std::logic_error& ) ou catch ( std::exception& ) ou aussi catch ( std::logic_error ) ou catch ( ... ).
    Mais std::logic_error n'est pas une Exception.

  3. #3
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut
    Bonjour,

    merci de ta réponse rapide, mais je ne comprends pas ma class Exception hérite de std::exception !
    Alors peut-être que mes compétences en C++ sont trop limitées, mais alors comment puis-je créer une clase d'exception interceptant mes propres Exception et std::exception, enfin TEST et TEST2 ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Tu dis toi-même que ton Exception hérite de std::exception, et n'est donc pas une std::logic_error.
    Donc forcément si tu throw une std::logic_error, ben tu peux pas l'attrapper dans une Exception. Ni l'inverse.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut
    pourtant le code suivant intercepte bien l'exception en question:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    try {
       throw std::logic_error("TEST");   // n'est pas interceptée dans le catch
    } catch (std::exception &e) {
        printf("%s\n",e.what());
     }

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Oui parce que std::logic_error hérite de std::exception et en tant que tel la relation entre elles est "est un". Une std::logic_error est une std::exception.
    Ton Exception n'est pas une std::logic_error.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    std::logic_error hérite de std::exception (comme toutes les exceptions du standard).

    Par conséquent, std::logic_error et Exception sont des std::exception, mais Exception n'est pas une std::logic_error et std::logic_error n'est pas Exception.

  8. #8
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut
    Ok je pige mieux, alors comment puis-je écrire ma propre class d'exception héritant de toute les exception standard, puis que je ne peux utiliser directement std::exception parque impossible de faire ma propre exception du style :
    throw exception("TEST");

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Si tu veux intercepter toutes les exceptions standards, tu interceptes std::exception et pas std::logic_error ou ta classe Exception.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut
    On revient à ma question initiale, pourquoi ma class Exception n'intercepte pas les exe standards?

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Faut lire et comprendre ce qu'on écrit.
    Citation Envoyé par Bousk Voir le message
    Oui parce que std::logic_error hérite de std::exception et en tant que tel la relation entre elles est "est un". Une std::logic_error est une std::exception.
    Ton Exception n'est pas une std::logic_error.
    Parce que ta classe Exception est une spécialisation d'un type d'exception standard donc non tu ne peux pas intercepter toutes les exceptions standards avec Exception vu que toutes les exceptions standards ne sont pas des Exceptions.
    C'est un peu le niveau 0 de la hiérarchie de classe, de l'héritage et la relation est-un.

    Si je te donne un rectangle de côtés A et B et un carré de côté A, tu pourrais mettre le carré dans la forme rectangulaire, le carré étant un rectangle particulier dans ce cas.
    Ta classe Exception est un cercle, ça n'a juste rien à voir.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut
    Ok, c'est plus clair, désolé si je ne suis pas très à l'aise avec ces notions. Alors comment puis je crée ma class héritant de toutes ces exceptions ? Héritages multiples ?

  13. #13
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Visiblement tu ne comprends toujours pas comment fonctionne l'héritage.

    Quel problème essayes-tu de résoudre et pourquoi catcher std::exception n'est pas suffisant ?

  14. #14
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 637
    Par défaut
    Salut,

    Pour te permettre de comprendre, un petit schéma semble s'imposer. Désolé, mais il va prendre la forme d'un dessin en ASCII ART

    Voici la situation dans laquelle tu es:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    classe de base                    std::exception
                                              / \    hérite: toutes les classes de 
                                             /   \   la deuxième ligne sont des std::exception
     défini comme tel par la SL         <-- /     \ -->défini comme tel par toi          
                                           /       \ 
                           std::logical_error      Exception
    (normalement, dans un schéma UML, il devrait y avoir une flêche en triangle pointant vers std::exception, malheureusement, les limites de l'ASCII ART ne me permettent pas de la représenter )
    Cela implique:
    1. que la classe std::logical_error EST-UN(e) std::exception
    2. que ta classe Exception EST-UN(e) std::exception


    Or, il faut l'admettre, la notion d'héritage est très mal desservie par cette expression "EST-UN(e)" car elle a beau être "simple à retenir", elle laisse croire que la relation d'héritage pourrait s'appliquer entre un carré et un rectangle sous prétexte que l'on a tous appris à l'école ... qu'un carré EST-UN rectangle (ayant quatre coté égaux / deux diagonales perpendiculaires).

    Or il se fait que le carré n'est -- éventuellement -- qu'un "état très particulier" du rectangle qui nécessiterait "simplement" d'avoir une fonction membre estCarre renvoyant true si les quatre côtés du rectangle sont égaux.

    Car le fait est que la notion d'héritage est dirigée par le principe de base connue sous l'acronyme LSP (pour Liskov Substitution Principle ou principe de substitution de Liskov).

    Si cela t'intéresse, je t'expliquerai pourquoi il est impossible d'envisager l'héritage entre un carré et un rectangle à cause de ce principe. Seulement, comme je prévois déjà de faire une réponse beaucoup trop longue, je préfère attendre que tu en fasse la demande

    Donc, pour en revenir à nos moutons, l'expression qu'il "serait pas mal d'utiliser" (dans un monde idéal) ressemble d'avantage à
    PEUT PASSER POUR ETRE UN
    ou même, histoire de reprendre le mot le plus important que l'on trouve dans le nom du principe qui régit l'héritage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PEUT ETRE SUSBSTITUE A UN(e)
    Nous en arriverions donc avec cette expression à dire que
    • std::logical_error PEUT ETRE SUBSTITUEE A UNE std::exception (comprend: on peut transmettre une std::logical_error à tout ce qui s'attend à receevoir une std::error)
    • ta classe Exception PEUT ETRE SUBSTITUEE A UNE std::exception (comprend: on peut transmettre un objet du type de ton Exception à tout ce qui s'attend à receevoir une std::error)

    Après avoir exprimé les choses sous cette forme (qui est quand même beaucoup plus correcte et censée ), il nous "suffira" d'ouvrir un peu les yeux pour nous rendre compte qu'il n'y a aucun lien direct entre la classe std::logical_error et ta classe Exception.

    Et surtout de nous rappeler que la notion d'héritage est "à sens unique" vu qu'il y a toujours une classe "de base" (ou "parent") et une classe "dérivée" (ou "enfant") et qu'il est généralement impossible d'inverser les deux.

    Si bien qu'il est tout à fait juste de dire, aussi bien pour std::logic_error que pour ta classe Exception qu'elles sont toutes les deux "suceptibles de passer pour être une std::exception" mais que l'on ne peut pas dire en retour que std::exception soit ... susceptible de passer pour être une std::logical_error ou ta classe Exception.

    Hé bien, dans le catch, il faut suivre la même logique:
    1. Ou bien tu récupère toutes les exceptions qui sont "susceptibles de passer pour être une std::exception", c'est à dire la classe std::exception (forcément ) ainsi queta classe Exception et la classe std::logical_error ainsi que toutes les autres classes d'exceptions (qui dérivent toutes de manière directe ou indirecte de std::exception) et toutes les classes dérivant (de manière directe ou indirecte) de std::exception qui trainent dans ton projet (et dans tes bibliothèques tierces)
    2. Ou bien tu récupère spécifiquement std::logic_error, ainsi que les classes qui en dérivent (de manière directe ou indirecte) qui "trainent" dans ton projet et dans les bibliothèques tierces (mais aucune des classes parentes std::logic_error)
    3. Ou bien tu récupère spécifiquement ta classe Exception, ainsi que les classes qui en dérivent (de manière directe ou indirecte) qui "trainent" dans ton projet (mais aucune des classes parentes de ta classe Exception)

    Et donc, si tu ne veux pas récupérer les std::logic_error ET ta classe Exception (ainsi que toutes les classes qui en dérivent de manière directe ou indirecte) mais que tu "te fous pas mal" de toutes les exceptions fournies par la bibliothèque standard qui ne sont pas spécifiquement std::logic_error, ben, tu n'a pas d'autre choix que de le faire en deux fois:
    • un catch récupère std::logic_error (et tout ce qui en dérive)
    • un autre catch récupère Exception (et tout ce qui en dérive)


    Tu peux, bien sur, les mettre au même endroit dans ton code, par exemple sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try{
        maybeThrowLogicError();
        maybeThrowException();
    }
    catch(Exception & e){ // L'ordre n'a aucune espèce d'importance
        // ...
    }
    catch(std::logic_error & e){
        //  ...
    }
    Mais tu peux aussi les mettre à des endroits ou à des niveaux différents, sous une forme qui serait alors proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    void maybeFail(){   // un point particulier où les deux cas de figure peuvent survenir
        maybeThrowLogicError();
        maybeThrowException();
    }
     
    void whatIfLogicError(){
        try{
             mayBeFail();
        }catch(std::logic_error &e){
            // on traite en priorité la logique (ca aurait pu être l'inverse :D)
        }
    }
    void whatIfAnyError(){
        try{
             whatIfLogicError();// la logique est traitée ici, plus besoin de s'en inquiéter
        }catch(Exception &e){
            // on traite ce qui relève de Exception uniquement ici
        }
    }
    Et, bien sur, tu auras compris que l'on peut complexifier les choses à loisir, en décidant -- pouruqoi pas, après tout -- de traiter "une partie du problème" soulevé par le fait que "std::exception" a été lancée "dans la fonction qui a été appelée par la fonction appelée par la fonction machin qui a été appelée par la fonction bidule", une autre partie "deux niveaux plus haut" dans la pile d'appels ainsi qu'une troisième partie encore trois niveaux plus haut et de faire pareil -- mais à des niveaux différents -- lorsqu'une exception de type Exception est lancée, "tout simplement" parce que ce sont les endroits où ces différentes gestions ont le plus de sens.

    Ce qu'il faut, finalement comprendre et retenir, c'est que le type de l'exception que tu attrapes avec catch sert de "filtre" évitant qu'absolument tout ce qui ne peut pas se substituer au type indiqué d'être pris en compte, et ce, même si le type indiqué peut quant à lui se substituer à "un autre". Parce que ce n'est pas "cet autre type" que l'on veut gérer, mais bien ... le type indiqué

    EDIT: Allez, un dernier pour la route:

    Notes que, si tu te dis que toutes les exceptions qui seront lancées dérivent de manière directe ou indirecte de std::logic_error et que tu veux récupérer en une seule fois les std::logic_error ET ta classe Exception (mais uniquement ces classes là), rien en t'empêche
    de faire hériter ta classe Exception de std::logic_error
    rattraper toutes les exceptions "pouvant se substituer à une std::logique error (en ce, y compris ta propre classe d'excpetion) avec un catch (std::logic_error &e)Evidemment, cela sous-entend qu'il doit y avoir du sens à se dire que "ta classe Exception représente une erreur particulière survenue à cause d'un problème de logique", vu que c'est la manière dont l'héritage aura pour résultat de la faire passer :$
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #15
    Membre éprouvé Avatar de uriotcea
    Homme Profil pro
    Ingénieur / physicien
    Inscrit en
    Septembre 2003
    Messages
    1 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur / physicien
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 301
    Par défaut
    Bonjour,

    Alors là bravo, j'apprécie vraiment.
    Que dire de plus à part, merci beaucoup pour cette longue et claire explication.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Exception non interceptée
    Par valda117 dans le forum PL/SQL
    Réponses: 0
    Dernier message: 28/08/2014, 22h43
  2. Interception d'exceptions non traitées
    Par vanitom dans le forum C++
    Réponses: 4
    Dernier message: 20/04/2009, 14h24
  3. Exception non intercepté
    Par uriotcea dans le forum C++
    Réponses: 5
    Dernier message: 26/05/2008, 13h06
  4. Réponses: 4
    Dernier message: 14/02/2005, 19h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo