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 :

opérandes constantes throw


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 25
    Points : 11
    Points
    11
    Par défaut opérandes constantes throw
    Salut,
    Comment je peux faire que dans le operator+= il programme envoie un message de error si
    opérande est const ?

    merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut, et bienvenue sur le forum...

    D'abord et avant tout, pourquoi voudrais tu le faire

    Typiquement, les opérateurs mathématique suivi d'affectation ( +=, -=, *=, /= ) renvoient une... référence sur l'objet en cours (qui seul sera modifié), et le compilateur refusera l'invocation des opérateurs si l'objet en cours est constant...

    En effet, si tu as une classe proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class MaClass
    {
        public:
            MaClass& operator+=(MaClass const & rhs)
            {
                /* le calcul "qui va bien" */
                return *this;
            }
    };
    le code suivant sera accepté (parce que c1 est non constant)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void foo()
    {
        MaClass c1;
        MaClass c2;
        c1+=c2;
        /* ceci fonctionne aussi  car c3 ne sera pas modifié */
        MaClass const c3;
        c1+=c3;  
    }
    Par contre, le code suivant sera refusé dés la compilation parce que l'objet en cours (c4) est constant et que tu ne peux invoquer que les fonctions déclarées constantes au départ d'objets constants
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void bar()
    {
        MaClass const c4;
        MaClass c5;
        c4+=c5; 
    }
    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

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Je veux just changer le error message pour que ca soit plus clair...

    Comment je peux utiliser try/catch pour controler le operator>> (si le type de Elem n'ai pas bonne)


    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
    template <typename Elem, size_t N>
     
    std::istream& operator>> (std::istream &input, Poly_S<Elem, N> &pol) {
     
     
     
        size_t deg, i;
     
        std::cout << "Degre du Poly (MAX :" << N << ") : ";
     
        std::cin >> deg;
     
        deg++; // Dimension = degre +1
     
        if(deg> N+1) throw "Degre for Poly statique is too big";
     
        else {
     
            // Initialisation des cases non utilisés par le Poly à 0
     
            for(i=N; i>deg-1; i--)
     
                pol[i]=Elem();
     
     
     
            for(i=deg-1;i>0;i--) {
     
                std::cout << "Coefficient d'ordre "<<i<<" ? ";
     
                std::cin >> pol[i];
     
            }
     
     
     
            std::cout << "Coefficient d'ordre "<<i<<" ? ";
     
            std::cin >> pol[i];
     
     
     
            return input;
     
      }
     
    }

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Comme je te l'ai expliqué, si tu essaye de passer un objet constant comme paramètre d'une fonction qui attend un objet non constant, l'erreur se produit directement au moment de la compilation.

    L'erreur que tu obtiens est alors propre au compilateur, et il est impossible de les modifier.

    Lorsque tu lance une exception avec throw et que tu la récupère dans un bloc try... catch, il s'agit d'erreurs qui surviennent lors de l'exécution du code qui, fatalement, survient beaucoup plus tard que la compilation

    De plus, tu nous parle dans ton premier message de l'opérateur += et dans le second de l'opérateur >> (que tu manipule d'ailleurs relativement mal, et qui ne me semble pas être des mieux adaptés à ce que ton code reflète )

    Je te conseillerais donc volontiers de réfléchir un peu à la citation de ma signature et de remettre un peu d'ordre dans tes différentes idées.

    Et, si je peux me permettre un dernier conseil, tu devrais réfléchir à déléguer correctement les différentes responsabilités: si une fonction a plus d'une responsabilité, c'est sans doute qu'elle en a trop
    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

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    merci pour les conseil en fait j'ai un classe polynome qui est un template de Elem,est taille de polynome
    et je veux recharger operator>>
    Est-ce que c'est pas bonne mon érciture?
    Est-ce que avec try/catch je peux récupérer les erreur dans ce style mouvais valeur pour taille ou Elem?

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Hrayr Voir le message
    Je veux just changer le error message pour que ca soit plus clair...

    Comment je peux utiliser try/catch pour controler le operator>> (si le type de Elem n'ai pas bonne)


    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
    template <typename Elem, size_t N>
     
    std::istream& operator>> (std::istream &input, Poly_S<Elem, N> &pol) {
     
     
     
        size_t deg, i;
     
        std::cout << "Degre du Poly (MAX :" << N << ") : ";
     
        std::cin >> deg;
     
        deg++; // Dimension = degre +1
     
        if(deg> N+1) throw "Degre for Poly statique is too big";
     
        else {
     
            // Initialisation des cases non utilisés par le Poly à 0
     
            for(i=N; i>deg-1; i--)
     
                pol[i]=Elem();
     
     
     
            for(i=deg-1;i>0;i--) {
     
                std::cout << "Coefficient d'ordre "<<i<<" ? ";
     
                std::cin >> pol[i];
     
            }
     
     
     
            std::cout << "Coefficient d'ordre "<<i<<" ? ";
     
            std::cin >> pol[i];
     
     
     
            return input;
     
      }
     
    }
    Bon, commençons par le commencement...

    Normalement, l'opérateur >> est ce que l'on appelle un opérateur de flux.

    Dans le cas de >>, le passage de l'information va du flux (le fichier, ou le clavier, par exemple) vers la donnée.

    De plus, le premier paramètre de la fonction (parce qu'un opérateur n'est jamais qu'une fonction bien déguisée ) est... une référence vers le flux d'entrée à manipuler.

    L'idée générale est, simplement, de se permettre d'écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Polynome p;
    std::cin >> p;
    Dans le code que tu nous présente, il serait donc intéressant d'utiliser le flux passé en paramètre (nommé input) plutôt que carrément cin.

    Seulement, cin n'est qu'un des type de flux qui existe d'origine: c'est le flux d'entrée standard, généralement associée au clavier.

    Or, il existe d'autres flux d'entrées, tels que les fichiers (ifstream pour le flux d'entrée) ou les flux de conversion en chaines ((i)stringstream) qui sont également susceptibles de réagir avec la surcharge de l'opérateur >> prenant un istream comme premier paramètre.

    Tu ne devrais normalement pas surcharger l'opérateur >> tel que tu le fais, mais tu devrais plutôt créer une fonction membre "classique" que tu nommerais, par exemple askValue (pour que le nom indique ce que tu fais), et qui prendrait la forme 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
    /*  je passe la déclaration des template */
    class Polynome
    {
        public:
            void askValue()
            {
     
                /* traitement complet   comme*/
                std::cout<<"blabla";
                std::cin>> truc;
                std::cout<<"bidule";
                std::cin>>machin;
            }
    };
    En effet, si, plus tard, toi (ou quelqu'un d'autre) regarde la déclaration de ta classe Polynome, il va voir que tu as redéfini l'opérateur >>.

    Cette personne peut donc être tentée de l'utiliser avec... n'importe quel type de flux d'entrée, et pourrais donc essayer d'écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::ifstream ifs("fichier.txt");
    Polynome p;
    ifs>>p;
    qui, tu n'y a peut être pas pensé, aura un comportement pour le moins... surprenant étant donné que ton implémentation:
    • utilise explicitement le flux de sortie standard std::cout (ce qui est encore le moins grave)
    • utilise explicitement le flux d'entrée standard std::cin (ce qui l'est beaucoup plus)


    Ensuite, comme je te l'ai indiqué, il faut veiller à déléguer correctement les différentes responsabilités, et, tant qu'à faire, il faut utiliser au maximum l'idiome RAII (Ressource Acquisition Is Initialisation).

    Le RAII consiste à tout faire pour que l'instance d'un objet soit utilisable (et correctement initialisée) dés le moment de la construction.

    Et ca, ca devrait se faire... en prévoyant le constructeur adéquat.

    L'idée est donc de séparer l'étape qui consiste à gérer l'introduction des différentes valeurs de l'étape qui consiste à créer ton polynome, 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
    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
    template <typename T>
    class Polynome
    {
        private:
            std::vector<T> elems_;
        public:
            /* par défaut, il n'y a aucun élément dans le polynome */
            Polynome():elems_(){}
            /* mais nous pouvons créer un polynome avec un nombre
             * quelconque d'éléments existants
             */
            explicit Polynome(std::vector<T> const & e):elems_(e){}
            /* ou en sachant quel est le degré maximal */
            explicit Polynome(size_t deg):elems_(deg+1){}
            size_t size() const{return elems_.size();}
            /* permettons d'accéder aux éléments par leur index */
            T const & operator[](size_t index) const
            {
                if(index>= elems_.size())
                    throw std::out_of_range();
                return elems_[index];
            }
            /* permettons de rajouter un élément à la fin */
            void push_back(T const & toadd)
            {
                elems_.push_back(toadd);
            }
            /* et de supprimer l'ensemble des éléments */
            void clear(){elems_.clear();}
            /* Mais rien ne nous empêche d'accepter de définir le polynome
             * au départ d'un flux (autre que std::cin
             */
            friend istream& operator>>(istream & input, Polynome & p)
            {
                 /* supprimons les coefficients existants... */
                 p.clear();
                 /* Il faut bien choisir un format pour le flux...
                  * cet opérateur ci va considérer que le flux est représenté
                  * au format CSV, tous les coefficients (y compris les nuls)
                  * sur la même ligne et séparés par une virgule
                  */
                 std::string temp;
                 std::getline(input, temp)
                 std::stringstream ss;
                 ss<< temp;
                 T value;
                 char c;
                 while((ss>value))
                 {
                      p.push_back(value);
                      ss>>c;
                 }
            }
    };
    template<typename T>
    Polynome<T> createPolynome()
    {
        /* le tableau de coefficients */
        std::vector<T> coefs;
        cout<<"Quel est le degré du polynome ?";
        size_t deg;
        cin>>deg;
        /* réservons d'un seul coup tout l'espace nécessaire */
        coefs.reserve(deg+1);
        /* introduisons les coefficients dans l'ordre croissant */
        for(size_t i=0;i<deg+1;++i)
        {
            int c;
            std::cout<< "Quel est le coefficient pour X^"<<i<<" ?";
            std::cin >> c;
            coef.push_back(c);
        }
        /* créons le polynome et renvoyons  le */
        return Polynome(coefs);
    }
    Enfin, il faut comprendre que ce qui est lancé par throw (et qui est géré dans la partie catch d'un bloc try catch) est... une exception.

    Il faut aussi comprendre qu'une exception est un événement
    • dont on espère qu'il n'arrivera pas (qu'il surviendra... exceptionnellement)
    • qui place un objet de ton application dans un état invalide (ou qui risque de le faire)
    • dont (une partie de la) la résolution doit être laissée à la fonction appelante (ou à une ou plusieurs des fonctions appelantes qui ont mené à cet événement).
    La tentative de définir N+1 valeurs alors qu'il n'en faut normalement que N n'entre, à mon sens, pas dans cette définition des exceptions.

    Et ce, d'autant plus qu'il "suffit" d'adapter la logique pour qu'il n'y ait que N itérations d'introduction de valeurs, ainsi que je te l'ai montré plus haut

    Par contre, il est cohérent de lancer une exception si l'on essaye d'accéder à un index supérieur à l'index maximal accessible car l'origine se trouve vraisemblablement... au moment où tu as déterminé l'index souhaité
    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

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    En fait c'est un projet où je dois recharger l'opérateur >>,l'opérateur << ...
    ca doit être flux parce qu'on entre les valeur de polynome en clavier.
    J'ai un code come ca
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Poly_S<double,5> polyS_double;
    cout<<"Entre le polynome statique avec element double"<<endl;
    cin >> polyS_double;
     cout << polyS_double<<endl;
    Dans le cas où le Éléments de polynôme qu'on entre est Complexe et on entre un rationnel pas exemple ou char c'est pas un exception?
    ou pour la taille de polynôme au lieu de etntre un size_t on entre un char c'est pas un exception?


    P.S. ce que je veux faire c'est dans le cas d'opérande erronée ?
    Détection et traitement d'exception (try / catch).

Discussions similaires

  1. requete SELECT avec un nombre constant
    Par gurumeditation dans le forum Requêtes
    Réponses: 3
    Dernier message: 04/07/2003, 20h04
  2. Gestion des constantes
    Par valfredr dans le forum XMLRAD
    Réponses: 5
    Dernier message: 18/06/2003, 16h23
  3. opérateur non applicable à ce type d'opérande
    Par Amon dans le forum Langage
    Réponses: 3
    Dernier message: 11/06/2003, 18h07
  4. [ADO] Constantes des types de champ
    Par SpaceFrog dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 05/09/2002, 11h08
  5. Au sujet des constantes
    Par FranT dans le forum Langage
    Réponses: 8
    Dernier message: 09/08/2002, 11h03

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