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 :

Lancer ses propres exceptions


Sujet :

C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut Lancer ses propres exceptions
    Bonjour à tous,

    J'aimerai faire ma gestion d'erreur autour des exceptions. Je possède une classe de conversion et voici son code:

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
     
    // Code d'une fonction dans ma classe de conversion
    void CConverter::ToInt(const char* sIn, int& iOut)
    {
    	try
    	{
    		iOut = lexical_cast<int>(sIn);
    	}
    	catch(std::exception)
    	{
    		throw new CConvertException("const char*", "int&", sIn);
    	}
    }
     
    // Code de la fonction appelante
    try
    {
    	CConverter::Instance().ToInt(sString.c_str(), iValue);
    }
    catch(CConvertException ex)
    {
    	LogManager::Instance() << ex.What();
    }
     
    // Classe de CConvertException
    #include "../../Exception/CException.h"
     
    namespace kin
    {
    	namespace utils
    	{
    		namespace conversion
    		{
    			namespace exceptions
    			{
    				class CConvertException : public kin::utils::exception::CException
    				{
    				public:
    					CConvertException(
    						const std::string& sFromType,
    						const std::string& sToType,
    						const std::string& sValue,
    						const std::string& sMessage = "Conversion impossible.");
    				};
    			};
    		};
    	};
    };
     
    // Classe CException
    #include <exception>
    #include <string>
    #include <vector>
    #include <map>
     
    namespace kin
    {
    	namespace utils
    	{
    		namespace exception
    		{
    			class CException : public std::exception
    			{
    			public :
    				CException(const std::string& sMessage, CException* oOriginException = NULL);
    				CException* GetOriginException();
    				const char* what() const throw();
     
    			protected :
    				std::string m_sMessage;
    				void AddCause(const char* sCause);
    				void AddParam(const char* sKey, const char*sValue);
     
    			private:
    				std::vector<const char*> m_oCauseVector;
    				std::map<const char*, const char*> m_oParamMap;
    				CException* m_oOriginException;
    			};
    		};
    	};
    };
    Voilà, lors du "throw", ça me renvoi une exception non géré, alors que l'appelle de celle-ci est entouré d'un try/catch :s

    Donc je ne comprends pas, CException dérive de std::exception, et CConvertException dérive de CException, le catch "attrape" bien les exception de type CConvertException...

    Quelqu'un peut m'éclairer?

    Merci beaucoup

    A bientôt

  2. #2
    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
    Et en attrapant ton std::exception par référence ?

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Merci

    J'ai mis catch(std::exception& ex) et c'est pareil (unhandle exception) :'(

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Ha c'est bon, j'suis bête, fallait mettre catch(CConvertException* ex) vu que je lance le throw avec un new derrière...

    Merci beaucoup

  5. #5
    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
    Ah oui... Quelle idée d'allouer une exception dynamiquement

    Enfin si tu y tiens, tu peux tout de même attraper un std::exception*

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Bah c'est la première fois que je fais ça...

    En général on fait ça comment?

    merci

  7. #7
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    En général, on récupère un "const MonException& exception"

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Ok merci beaucoup, j'essaye

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par mister3957
    En général on fait ça comment?
    "throw by value, catch by reference"
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Petite question, pourquoi tu crées ta propre classe d'exception alors qu'il y en a déja une pour la fonction lexical_cast? (lexical_cast_exception ou quelque chose qui y ressemble)
    Autre chose, c'est moyen moyen de dériver de std::exception, ça t'oblige à taper une bonne partie de code supplémentaire car ce n'est pas le but de cette classe que l'utilisateur l'utilise directement. Idéalement, il faut faire dériver de std::logic_exception ou bien de std::runtime_exception (probablement runtime_exception dans ce cas) qui dérivent chacune de std::exception.

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    C'est pour transformer la lexical_cast_exception.

    Ainsi, une lexical_cast_exception donnera lieu à une CConvertException qui elle donnera lieu à une CConfigBadCastException.

    Dans chaque exception, j'ai réussit à en référencer une autre, et maintenant je peux voir tous les niveaux. Pour l'exemple ci dessus j'aurai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    "Impossible de récupérer une valeur dans le fichier de configuration
        Origine:
            Impossible de convertir une valeur".
    J'ai rajouté également une liste de paramètre et de cause dans les exception. Comme ça, dans le constructeur de chaque classe, on peut spécifier des paramètres qui seront donné lors de lancement.

    Le what renvoi juste le message, et j'ai rajouter une methode FullMessage qui me permet de formatter un beau message en prenant en compte les paramètres, les causes ainsi que l'eventuelle origine.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    "Impossible de récupérer une valeur dans le fichier de configuration
        Causes possibles:
            - Le fichier de configuration n'est pas correctement formatté
            - Une autre cause possible
            - Et enfin une dernière
        Paramètres:
            - Clé : 'i'
        Origine:
            Impossible de convertir 'n' en integer.
                Paramètres:
                    - Valeur : 'n'
                    - Type : string
                    - Cast : int"
    Et ainsi de suite.

    Grâce à ça, je peux remonter les problèmes jusqu'à la source et tous mes message d'exceptions sont homogènes car leur construction est dans la classe de base. J'ai casiment plus besoin de relancer le programme en mode débug jusqu'à l'exception car je sais d'emblée où elle se trouve.

    J'espère que c'est bien ce que j'ai fait, peut être il faudrait rajouter la ligne et le fichier avec les __LINE__ et __FILE__ pour mieux la situer...

    Quand je vois, dans mon boulot, les messages que rencontrent les utilisateurs... la hotline ne peux rien faire, on est sans cesse en train de leur demander de nous renvoyer tout le répertoire d'installation, les clés dans la base de registre pour relancer chez nous jusqu'à ce que ça plante...

  12. #12
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Citation Envoyé par zais_ethael
    Autre chose, c'est moyen moyen de dériver de std::exception, ça t'oblige à taper une bonne partie de code supplémentaire car ce n'est pas le but de cette classe que l'utilisateur l'utilise directement. Idéalement, il faut faire dériver de std::logic_exception ou bien de std::runtime_exception (probablement runtime_exception dans ce cas) qui dérivent chacune de std::exception.
    std::exception donne un what() qui est virtuel et surchargé dans toutes les autres exceptions standards ou presque - comme runtime_error, bad_alloc, ... -, donc pas de pb de dériver de std::exception. Mais il y a une hiérarchie d'exception qu'il faut essayer de respecter par logique.

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Oui mais il ne contient pas de std::string en interne et pas non plus de constructeur prenant un string en argument (sauf dans visual studio d'après ce que j'ai pu voir - ce qui peut-être une cause de non-portabilité).
    Mais l'interet principal est bien sur de respecter la hiérarchie

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Au départ je voulais générer le message dans le what().

    Mais j'ai pas réussit. En effet, pour les concaténation, je me suis appyué sur std::string. Mais le what renvoir un char*, alors je faisais return sWhat.c_str().

    Sauf qu'une fois le what() passé, la std::string n'existe plus, et donc la valeur de retour non plus.

    J'ai bien essayé de recréer un char*, mais çame faisais faire un new dans la fonction que chaque catch derrière devait supprimer, et j'ai trouvé ça vraiment pas bon.

    Autre chose, si on cherche à afficher le message différemment, on voidra peut-être parcourir les exceptions pour accéder aux informations librement dans être cantonné à ce message formatté, donc j'ai trouvé plus utile pour la suite de dissocier le message initiale, les paramètres et les causes du message formatté.

    Imaginez que je voudrais afficher ça dans un treeview, bah si je ne propose qu'un texte pré formatté, on pourra rien faire, donc je propose tout

    J'pense que j'suis dans le bon là.

Discussions similaires

  1. Réponses: 7
    Dernier message: 09/04/2010, 18h48
  2. creer ses propres exceptions
    Par hebus666 dans le forum SQL Procédural
    Réponses: 0
    Dernier message: 09/12/2007, 15h36
  3. Creer ses propres exceptions ?
    Par Seth77 dans le forum C#
    Réponses: 4
    Dernier message: 05/05/2007, 17h36
  4. [JNI] creer ses propres exceptions
    Par Batou dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 23/08/2006, 04h01
  5. Créer ses propres exceptions
    Par Neilos dans le forum C++Builder
    Réponses: 10
    Dernier message: 13/06/2006, 18h44

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