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 :

Utilisation adéquate des exceptions


Sujet :

C++

  1. #1
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut Utilisation adéquate des exceptions
    Bonjour, je sais qu'un topic a recemment été ouvert sur le sujet des exceptions mais je trouvais qu'il était peu approrié à mon problème.


    Je me fais une petite classe Utilitaire, qui comporte exemple une fonction pour convertur un paramètre T en std::string.


    Est-ce que l'utilisation des exceptions est adéquates dans le contexte suivant?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <class T>
    std::string Util::tostr(T value) 
    {
        std::ostringstream oss;
        try {
            oss << value;
        }
        catch (const std::exception& error) {
            std::cerr << error.what() << std::endl;
        }
        return oss.str(); 
    }
    J'ai ajouter ce traitement d'exception car supposons que le programmeur (lorsque je ne serai plus en stage ici) utilise Util::tostr pour tenter de convertir quelque chose en string (un objet X par exemple) et que cela est impossible, cela lui lance une exception.


    Est-ce adéquat? Merci

  2. #2
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Salut !

    Alors, non ce n'est pas adéquate, pour la simple est unique raison que la déterminisation des templates (le fait de remplacer les types génériques par des vrais types) se fait à la compilation, et non pas à l'exécution...

    donc il te sera (normalement) signalé à la compilation que l'opérateur n'existe pas.
    de plus, même en supposant que ça fonctionne, ici, avec ton catch, l'exception ne sortira de toutes façon jamais de la fonction...donc le programmeur ne la verra pas...
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  3. #3
    Rédacteur
    Avatar de bigboomshakala
    Homme Profil pro
    Consultant Web .NET
    Inscrit en
    Avril 2004
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Web .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2004
    Messages : 2 077
    Par défaut
    Citation Envoyé par vdumont
    J'ai ajouter ce traitement d'exception car supposons que le programmeur (lorsque je ne serai plus en stage ici) utilise Util::tostr pour tenter de convertir quelque chose en string (un objet X par exemple) et que cela est impossible, cela lui lance une exception.
    si tu passe un objet pour lequel il n'y a pas de conversion implicite vers un type supporté par l'opérateur << l'erreur est détectée à la compilation.

  4. #4
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    Ok merci


    Mais Swoog, si j'ai exemple:


    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class Util 
    {
      public:
      Util();
      ~Util();
     
      template <class T>
      static std::string tostr(T);      // Convertir en string
     
      template <class T>                // Convertir en entier
      static int toint(T);
    }; 
     
    template <class T>
    std::string Util::tostr(T value) 
    {
        std::ostringstream oss;
        oss << value;
        return oss.str(); 
    }
     
    template <class T>
    int Util::toint(T value) 
    {
        std::istringstream iss(value);
       int integer;
        iss >> integer;
        return integer;
    }
    NB: La déclaration et l'implémentation sont tout 2 dans un fichier .h dans ce cas ci.


    Ca fonctionne quand je l'appel dans mon code en faisant Util::toint("blabla");
    Exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    todraw.insert(std::make_pair(Util::toint(nomaillage),childvalue));
    Je comprend pas trop le problème des templates que tu essaies de m'expliquer. Merci!

  5. #5
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    essaie ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class NCLASS_TEST { };
    [...]
    NCLASS_TEST test;
    std::cout << Util<NCLASS_TEST>::tostr(test) <<endl;
    tu devrais comprendre ce que je veux te dire
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  6. #6
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    Et bien ca ne fonctionnera pas car l'opérateur << ne sera pas capable de faire la conversion implicite d'un objet NCLASS_TEST???

    Mais de la façon que je l'utilise est-ce que c'est mauvais?

    Et pourquoi est-ce que tu utilises Util<NCLASS_TEST> toint(test);

    En passant test en paramètre le T est donc considéré comme un type NCLASS_TEST non? Si oui pourquoi indiquez NCLASS_TEST entre < > ?

  7. #7
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ce qu'il veut dire, c'est que le seul cas[*] où une injection dans un flux peut échouer, c'est si aucun opérateur << n'est défini entre le type en question et un ostream. Mais ça ce sera géré à la compilation, pas à l'exécution.

    Pour l'extraction par contre (>>), tout un tas d'erreurs peuvent survenir, et là il faudra effectivement une bonne gestion des erreurs.

    Par ailleurs, que je sache, les flux ne lancent jamais d'exception, ils gèrent les erreurs via des flags ; pour gérer les erreurs il faut donc tester le flux et non pas tenter d'attraper des exceptions.

    [*] Il y a sûrement des cas où un flux de sortie provoque une erreur, mais ça doit relever du pinaillage

  8. #8
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Citation Envoyé par vdumont
    Et pourquoi est-ce que tu utilises Util<NCLASS_TEST> toint(test);

    En passant test en paramètre le T est donc considéré comme un type NCLASS_TEST non? Si oui pourquoi indiquez NCLASS_TEST entre < > ?
    Désolé, j'ai cru que le template était sur la classe entière, il ne faut pas le mettre en effet, j'ai confondu
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  9. #9
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    Merci pour la réponse Laurent.

    Je devrais donc faire quelque chose du genre if (iss >> integer)



    Autre chose que je me demandais, dans le cas ou il y a eu un échec, quel genre de valeurs je devrais retourné pour signaler qu'il y a eu un problème? Le classique -1 serait-il approprié?

  10. #10
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Citation Envoyé par vdumont
    Autre chose que je me demandais, dans le cas ou il y a eu un échec, quel genre de valeurs je devrais retourné pour signaler qu'il y a eu un problème? Le classique -1 serait-il approprié?
    Dans ce cas par exemple, la lever d'une exception serait apropriée, c'est le plus sûr des messages d'erreur ^^
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  11. #11
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Les exceptions, c'est très délicat. Etant donné que tu as une fonction template, il faut partir du principe que T peut balancer des excetions à tout bout de champ. Si pour les types de base, operator<< de la lib standard ne lève pas d'exception d'impossibilité de conversion à ma connaissance (quoique pour les flottants j'ai un doute), il n'est pas exclus que l'opérateur d'un type utilisateur T le fasse.
    Si tu veux paniquer un peu à propos des exceptions:
    http://www.awprofessional.com/conten...g_Article.html
    Pour moi ton catch ne sert à rien, à part
    - imposer que l'exception est ignaurée
    - écrire un message d'erreur
    donc ton code court-circuite la gestion des erreurs du client.
    C'est lui qui t'a filé un type que tu peux pas convertir ? => c'est à lui de se débrouiller avec ce problème.
    Ton code doit informer de l'erreur, et non la traiter.

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Oui, dans ce cas l'exception est appropriée ; renvoyer une valeur particulière (-1) est une mauvaise idée : que se passe-t-il si l'utilisateur veut convertir -1 ?

    Et puis typiquement tu n'auras pas une fonction toint, mais une fonction template qui prend en paramètre n'importe quel type, comme tostring. Et là l'exception s'impose puisque tu ne sais même pas quel type va être utilisé, donc tu ne peux pas le gérer toi-même.

  13. #13
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    Quel genre de throw je devrai utiliser parcontre?!

  14. #14
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Citation Envoyé par vdumont
    Quel genre de throw je devrai utiliser parcontre?!
    Dans l'absolu, le mieux serait peut-être de créer ta propre exception... (il suffit de créer une classe comme une autre) une classe template qui permettrait de donner un accès à la variable qui a provoquer l'erreur... par exemple
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  15. #15
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    Voici ce que j'ai pensé faire
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    class Util 
    {
      public:
      Util();
      ~Util();
     
      template <class T>
      static std::string ToStr(T);      // Convertir en string
     
      template <class T>              // Convertir en entier
      static int ToInt(T);
    }; 
     
     
     
    template <class U>
    class ConversionFailure: public std::exception
    {   
       public: 
         virtual const char* what() const { return "Erreur lors de la tentative de conversion en .... à partir d'un objet ... "; }
    }; 
     
     
     
    template <class T>
    int Util::ToInt(T value) 
    {
        std::istringstream iss(value);
        int integer;
        if (! iss >> integer) throw ConversionFailure();
        catch (ConversionFailure<int>& e) {           
               std::cout << e.what() << std::endl;
        }
        return integer;
    }

    Je doute de ce que je fais plus haut, je suis aps très familié avec les exceptions.

    J'aimerais avoir 1 seule classe exception qui puisse traiter les erreurs de conversion à la fois de ToStr() et de ToInt(). Comment remplacer mes "..." bleu en gras dans la fonction what() ??? (Je veux savoir le type en quoi on a essayer de convertir et le type de l'objet qu'on a essayer de convertir).


    Merci beaucoup.

  16. #16
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Perso, j'aurais plutôt vu un truc comme ça :
    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
    template<class T>
    class ConversionFailure : public std::exception
    {
    <div style="margin-left:40px">private :
    <div style="margin-left:40px">const T& _inst;</div>
    public :
    <div style="margin-left:40px">ConversionFailure(const T& val) : _inst(val) { };
    virtual const char* what() const throw() { return "La conversion a echoue"; }
    const T& ToConvert() const { return this->_inst; }</div></div>}
     
    [...]
    template <class T>
    int Util::ToInt(const T& value) 
    {
    <div style="margin-left:40px">std::istringstream iss(value);
    int integer;
    if (! iss >> integer) throw ConversionFailure<T>(value);
    return integer;</div>}
    Dans tous les cas, il ne faut pas de catch, et il faut déclarer les paramètres de template dès le throw :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template <class T>
    int Util::ToInt(T value) 
    {
        std::istringstream iss(value);
        int integer;
        if (! iss >> integer) throw ConversionFailure<int, T>();
        return integer;
    }
    Citation Envoyé par Aurelien.Regat-Barrel
    Ton code doit informer de l'erreur, et non la traiter.
    donc throw : ok mais pas de catch !


    Pour ce qui est dans ton code, de récupérer les infos, il faut te tourner vers le RTTI (je crois) qui permet d'avoir des informations sur les types... cependant, quand on se retrouve devant une exception gérée, on sait d'où elle vient, et si l'exception n'est pas gérée, il y a normalement moyen de retrouver où elle a étée levée, donc je ne pense pas que ça te soit extrêmement utile
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  17. #17
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    Merci Swoog pour cette réponse très complète.

    J'ai cependant de la misère avec les deux lignes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    virtual const char* what() const throw() { return "La conversion a echoue"; }
     
    const T& ToConvert() const { return this->_inst; }

    La première ligne me confond car on dirait qu'elle a 2 fonctions sur la même ligne.

    La deuxième ligne je ne comprend pas comment sera utilisé le return. Et également à quoi sert la présence du 2ième const ??

    Merci beaucoup et pardonnez mon ignorance

  18. #18
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    alors pour la première, la mention throw() qui suit la mention const signifie que la fonction ne peut en aucun cas lever d'exception, c'est normalement demandé par le compilateur (en tous cas, par g++ et celui de Dev-C++ il me semble)...
    car la fonction what() de la classe std::exception possède cette propriété.

    pour la seconde, cela permet simplement d'avoir un accès à la variable qui a provoqué l'erreur...
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  19. #19
    Membre éclairé Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Par défaut
    A quoi sert la présence du 2ième const ??

    virtual const char* what() const throw() { return "La conversion a echoue"; }

    const T& ToConvert() const { return this->_inst; }

  20. #20
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Regarde plutôt boost::lexical_cast

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Utilisation détournée des exceptions
    Par Mens Pervincet dans le forum Général Java
    Réponses: 5
    Dernier message: 16/05/2010, 15h27
  2. [Oracle 8i - PL/SQL] Utilisation des exceptions
    Par Bahan dans le forum Oracle
    Réponses: 3
    Dernier message: 28/08/2006, 16h24
  3. [Exception] de l'utilisation des exceptions...
    Par Alec6 dans le forum Général Java
    Réponses: 7
    Dernier message: 16/09/2005, 17h53

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