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

Langage C++ Discussion :

Exception dans constructeur de classe refusé


Sujet :

Langage C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Par défaut Exception dans constructeur de classe refusé
    Bonjour à tous,
    Voici le problème: j'ai une classe, ICBond, qui prend dans son constructeur, 3 arguments, 2 adresses d'une autre classe ICAtom et un entier. Cependant, les 2 instances de classe ICAtom (qui sont des adresses) ne doivent pas être nulle. Donc un petit if pour vérifier, et si l'un des 2 est nul, je lance une exception. Le code marche parfaitement si les 2 atomes ont des adresses bien définis, mais si l'un d'entre eux à une adresse "nulle", j'ai un message d'erreur qui apparait à la fin de l'appel du constructeur, après avoir finis l'execution du catch et ce sans raison. Une idée ???

    Message d'erreur :
    Program received signal: “SIGABRT”.


    Code ICBond.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	class ICBond 
    	{
    	private:
    		ICAtom* Atom1;
    		ICAtom* Atom2;
    		BondType  Type;
    		bool Clear();
     
    	public:
    		ICBond(ICAtom* _Atom1, ICAtom* _Atom2, BondType _BType)throw (MolException);}
    Code de la classe d'exception :
    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
    class MolException: public std::exception
    {
    public:
        MolException(int numero=0, const std::string& phrase="", int level=0) throw();
     
    	virtual const char* what() const throw();
    	int getLevel() const throw();
    	int getNum() const throw();
     
        virtual ~MolException() throw()
        {}
     
    private:
        int m_numero;               // Numéro de l'erreur.
        std::string m_phrase;       // Description de l'erreur.
        int m_level;               // Niveau de l'erreur: 
    };
    Le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int main (int argc, char * const argv[]) {
    	ICAtom *Atm  = new ICNMole::ICAtom(1,1,1);
    	ICAtom *Atm2 = NULL;//new ICNMole::ICAtom(2,2,2);
    	ICBond *Bond = new ICNMole::ICBond(Atm,Atm2,ICNMole::Single);
     
    }
    Merci d'avance !!

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    Bonjour
    Citation Envoyé par gilims Voir le message
    à tous,
    ...je lance une exception...
    mais il n'y a personne pour la rattraper dans votre main, d'ou le problème

    protégez donc vos allocations avec un try - catch
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Par défaut
    exact !!! La raison est simple: j'ai oublié de le mettre dans le post !! c'était déjà mis auparavant. Grossière erreur de ma part. Voici le constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    ICBond::ICBond(ICAtom* _Atom1, ICAtom* _Atom2, BondType _BType)throw (MolException)   
    try
    {
    	if (_Atom1 == NULL)	  throw MolException(03001, "New Bond with a null atom",1);
    	if (_Atom2 == NULL)   throw MolException(03001, "New Bond with a null atom",1);
    	if (_Atom1 == _Atom2) throw MolException(03002, "New Bond between 1 identical atom",1);
    	Atom1=_Atom1; Atom2=_Atom2; Type=_BType;
    }
    catch(MolException &e) {
    	cerr<< e.what()<<endl;
    }

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Par défaut
    essaye ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ICBond::ICBond(ICAtom* _Atom1, ICAtom* _Atom2, BondType _BType)
    {
    	if (_Atom1 == NULL)	  throw MolException(03001, "New Bond with a null atom",1);
    	if (_Atom2 == NULL)   throw MolException(03001, "New Bond with a null atom",1);
    	if (_Atom1 == _Atom2) throw MolException(03002, "New Bond between 1 identical atom",1);
    	Atom1=_Atom1; Atom2=_Atom2; Type=_BType;
    }
    Et dans ton main:

    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
     
    int main()
    {
        try
        {
            ICBond bond( 0, 0, ICNMole::Single );
        }
        catch( const std::exception & e )
        {
             std::cout << e.what() << std::endl;
        } 
        catch( ... )
        {
            std::cout << "exception inconnue" << std::endl;
        }
    }

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Par défaut
    Désolé pour le temps de latence.

    En effet, cette façon de procédé marche. cependant, dans mon esprit (surement un peu fou je l'admets ), en mettant le try directement dans le constructeur, je voyais le moyen simple de ne pas avoir à le placer dans le main. Comme ca l'utilisateur qui déciderais de définir une nouvelle variable IBond aurait juste à rajouter vérifier si ca variable n'est pas un pointeur null plutot que de mettre un try catch à chaque fois qu'il fait une nouvelle IBond (sachant qu'il peux y en avoir quelques centaines de définis à chaque lancement du programme). Qu'en pensez vous ?

  6. #6
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    quoi que vous fassiez dans le constructeur vous ne pourrez pas demander à celui-ci de retourner un pointeur nul, tout ce que vous pouvez faire c'est qu'il retourne une instance sur laquelle l'application d'une opération isValid retourne faux
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par gilims Voir le message
    Qu'en pensez vous ?
    Que si ton utilisateur ne doit pas recevoir d'exception alors ton constructeur ne doit pas en lever. Mais tu dois, comme le dit Bruno, toujours retourner un objet valide si ton constructeur ne lève pas d'exception. Et/ou t'intéresser à la prog par contrat.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 638
    Par défaut
    Salut,
    Citation Envoyé par gilims Voir le message
    Désolé pour le temps de latence.

    En effet, cette façon de procédé marche. cependant, dans mon esprit (surement un peu fou je l'admets ), en mettant le try directement dans le constructeur, je voyais le moyen simple de ne pas avoir à le placer dans le main. Comme ca l'utilisateur qui déciderais de définir une nouvelle variable IBond aurait juste à rajouter vérifier si ca variable n'est pas un pointeur null plutot que de mettre un try catch à chaque fois qu'il fait une nouvelle IBond (sachant qu'il peux y en avoir quelques centaines de définis à chaque lancement du programme). Qu'en pensez vous ?
    Le fait est que le principe même qui est suivi lorsqu'une exception est lancée dans un constructeur est d'éviter l'obtention d'un objet qui soit dans un état incohérent.

    Or, bien souvent, si on détermine dans le constructeur qu'un objet se trouve dans un état incohérent, c'est, très certainement, parce qu'il y a eu "une couille dans le potage" avant que le constructeur ne soit appelé.

    On ne peut donc envisager d'apporter une solution à ce problème que... en dehors du constructeur

    Il faut aussi comprendre que le gros principe des exception est... de ne les récupérer que lorsqu'il est possible de les traiter en tout ou en partie.

    Si le traitement de l'exception n'est que partiel, il faut donc envisager de... la faire remonter "plus haut" pour assurer un traitement complet (qui peut être le fait de décider de quitter l'application... plus ou moins correctement, parce qu'il est impossible d'apporter de meilleur solution).

    L'affichage de l'erreur rencontrée ne peut en aucun cas être considéré comme une solution complète, car cela n'a qu'un effet "informatif" sur ce qui s'est passé.

    Si tu ne relance pas l'exception dans le constructeur, tu obtiendra bel et bien un affichage de l'erreur provoquée, mais, comme l'exécution du programme continue "comme si de rien n'était" après être passé dans le catch, l'objet créé sera considéré comme... valide par le système, et cela même, alors que l'utilisateur saura qu'il n'en est rien.

    Tu te doutes que ce n'est pas vraiment ce que tu veux, car l'utilisation d'un objet considéré comme valide par le système finira, tôt ou tard, par te "péter à la figure"
    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

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

Discussions similaires

  1. Exception dans le constructeur
    Par olive_le_malin dans le forum C++
    Réponses: 9
    Dernier message: 24/05/2007, 18h02
  2. Réponses: 18
    Dernier message: 28/02/2007, 10h23
  3. Réponses: 7
    Dernier message: 22/10/2006, 18h51
  4. exception dans un constructeur
    Par xxiemeciel dans le forum C++
    Réponses: 25
    Dernier message: 23/11/2005, 18h14
  5. Capture d'exception dans un constructeur
    Par declencher dans le forum Composants VCL
    Réponses: 8
    Dernier message: 03/02/2004, 12h52

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