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 :

"Gaussrand" et cnd_manual was not declared in this scope


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Janvier 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Bâtiment

    Informations forums :
    Inscription : Janvier 2014
    Messages : 2
    Par défaut "Gaussrand" et cnd_manual was not declared in this scope
    Bonjour,
    Dans mon projet informatique, je dois généré des nombres aléatoires suivant une loi gaussienne.
    J'utilise la fonction gaussrand qui me génére des nombres aléatoires selon une loi gaussienne de mean=0 et d'écart type=1. Ensuite avec 2 variables m(moyenne) et ecart(ecart) que l'utilisateur va saisir lui permet de générer des nombres aléatoires suivant une loi gaussienne avec ses paramètres.
    J'utilise une classe qui s'appelle gaussienne dans laquelle je déclare mes attributs et mes méthodes comme ceci :

    Code c++ : 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
    #ifndef GAUSSIENNE_H
    #define GAUSSIENNE_H
    #include <cstdlib>
    #include <cmath>
     
    class Gaussienne
    {
    private: // Pour respecter l'encapsulation car tous les attributs doivent être privé
     
        ////////////Déclarations des attributs//////////////
        double moy, ecartype;
     
    public :
        Gaussienne(double m, double ecart) : moy(m), ecartype(ecart) {}// constructeur
     
          /////////Declaration des fonctions///////////////
          double get_moy(double m);
          void set_moy (double m);
          double get_ecart(double ecart);
          void set_ecart(double ecart);
          double gaussrand();
          double cnd_manual(double x);
     
    };
     
    #endif // GAUSSIENNE_H

    Les fonctions gaussrand et cnd_manual sont implémentés dans un autre fichier.ccp. Dans mon main j'appelle donc ces 2 fonctions:

    Code c++ : 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
    #include <QCoreApplication>
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    #include <fstream>
    #include <cmath>
    #include "Gaussienne.h"
     
    using namespace std;
     
    int main()
    {
     
        double m, ecart;
        double nbpt,va,alea,p;
     
        cout << "Entrer une valeur moy :";
        cin >> m;
        cout << "Entrer une valeur Ecart type :";
        cin >> ecart;
        cout << "Entrer un nombre de point :";
        cin >> nbpt;
     
        srand(time(0));
     
        for(int i=0;i<nbpt;i++)
        {
            alea=gaussrand();
            va=ecart*alea+m;
            p=cnd_manual(alea);
            cout << "valeur aleatoire : " << va << "   Probabilte :" << p << "\n";
        }
    return 0;
    }
    Lorsque je compile, j'ai les messages d'erreur suivant:
    - 'gaussrand' was not declared in this scope
    - 'cnd_manual' was not declared in this scope


    Je pensais que c'était un problème de bibliothèque mais j'ai presque insérer tous les bibliothèques nécessaires. Je vous demande alors de l'aide pour surpasser ce problème qui persiste il y'a une semaine.
    Je vous remercie d'avance.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Par défaut
    Bonsoir. Tu as oublié de déclarer dans le fichier main.cpp les prototypes des fonctions gaussrand et cnd_manual.
    Tu dois avoir un fichier .h qui contient les déclarations des dites fonctions.
    Donc dans le main tu auras une lignes du genre
    #include "fichier_entete_manquant"

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Aucun lien avec l'oubli d'un #include, mais avec l'utilisation d'une classe.

    Les méthodes gaussrand() et cnd_manual() sont des méthodes de ta classe Gaussienne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Gaussienne
    {
          // ...
          double gaussrand();
          double cnd_manual(double x);
     
    };
    Tu ne peux donc pas les appeler ainsi comme de simples fonctions libres, tu as besoin d'une instance de la classe Gaussienne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Gaussienne instance(m, ecart);
    alea = instance.gaussrand();
    p = instance.cnd_manual(alea);

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

    Informations professionnelles :
    Activité : aucun

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

    Je voudrais juste intervenir sur un point qui me choque personnellement terriblement.

    C'est que ton code contient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Gaussienne
    {
    private: // Pour respecter l'encapsulation car tous les attributs doivent être privé
     
        double moy, ecartype;
     
    public :
        Gaussienne(double m, double ecart) : moy(m), ecartype(ecart) {}// constructeur
          double get_moy(double m);
          void set_moy (double m);
          double get_ecart(double ecart);
          void set_ecart(double ecart);
    /* ... */
    Et quand je lis ce code, la première chose que je remarque, c'est le commentaire associé à la définition de l'accessibilité privée :
    Pour respecter l'encapsulation car tous les attributs doivent être privé
    et que je le mets en relation avec les fonctions publiques:
    get_moy (qui ne devrait, au passage, pas prendre d'argument, mais qui devrait être déclarée comme constante) permet à l'utilisateur de récupérer la valeur connue en interne sous le nom de moy. Soit, cela peut se comprendre.

    Mais la fonction qui est déclarée juste après, c'est set_moy dont je présume que le but est de modifier la valeur de moy.

    Et là, je me dis qu'il y a quand même quelque chose qui cloche En effet, ces deux fonctions ont pour résultat de permettre à l'utilisateur d'avoir un accès "plein et entier" à la valeur de moy.

    Dés lors, je me pose la question de savoir pourquoi tu te fais ch..er à placer la valeur moy en accessibilité privée et à rajouter ces deux fonctions si, d'une certaine manière, il aurait été beaucoup plus facile de placer moy dans l'accessibilité publique

    Il n'y a en effet rien qui interdise de placer un attribut dans l'accessibilité publique!

    Ou plutôt -- car je sais avoir pris le problème à l'envers -- ton commentaire ment honteusement au lecteur du code parce que, en exposant la fonction get_moy, on peut considérer qu'il s'agit d'un service que tu es en droit d'attendre de la part de ta classe, mais, en exposant la fonction set_moy, tu brises littéralement l'encapsulation, vu que tu permets "au premier clampin venu" d'aller modifier la valeur

    Et je peux d'ailleurs faire les mêmes remarques en ce qui concerne la valeur ecartype et les fonctin get_ecart et set_ecart !

    Ce sur quoi je veux attirer ton attention par mon intervention, c'est qu'il ne suffit pas de déclarer une variable membre dans l'accessibilité privée pour assurer l'encapsulation !

    Notes d'ailleurs qu'il n'est absolument pas nécessaire d'utiliser le paradigme orienté objet pour pouvoir profiter de l'encapsulation : il suffit de faire en sorte que l'utilisateur n'ait pas à s'inquiéter de la manière dont les données sont représentées dans une structure.

    Veux tu la preuve de ce que j'avance La structure FILE du langage C en est un parfait exemple : personne n'a besoin de savoir exactement la composition de cette structure, parce que le seul moyen de la manipuler passe par un certain nombre de fonctions qui sont dédiées à sa manipulation.

    Si tu veux assurer l'encapsulation, ou plutôt, si tu veux profiter pleinement des bienfaits de l'encapsulation, tu dois t'assurer que les modifications apportées à l'état de ta structure seront systématiquement validées avant d'être prises en compte!

    Ici, tu parles de moyenne et d'écart-type. Ce sont, typiquement, des valeurs très volubiles dans le sens où elles dépendent d'un ensemble de valeurs sur lesquelles elles seront calculées.

    Si tu veux que ta classe prenne du sens, il faut que tout ce qui a trait au calcul de ces deux valeurs soit pris en charge par ta classe.

    Evidemment, cela implique qu'il faut que ta classe dispose de "tout le nécessaire" pour pouvoir calculer ces deux valeurs, et donc que tu devras aussi permettre à l'utilisateur de demander à ta classe de rajouter des valeurs au départ desquelles la moyenne et l'écart type seront calculées et -- peut être -- de permettre à l'utilisateur d'interroger la classe sur les valeurs permettant le calcul dont elle dispose.

    Au final, une classe utile ressemblera plutôt à quelque chose comme
    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
    class Gaussienne{
    public;
        /* on pourrait prévoir plusieurs constructeurs, dont l'un ou l'autre permettrait
         * de remplir le tableau lesValeurs avec des valeurs transmises dés la création
         * de l'objet...
         */
        void ajouterValeur(double toadd);
        /* ce sera peut etre intéressant :-D */
        size_t nombreDeValeurs() const{return lesValeurs_.size();}
        /* ce sera surement utile :-D */
        double obtenirMoyenne() const;
        /* ce sera surement utile :-D */
        double obtenirEcartType() const;
        /* je ne sais pas ce qu'elles font, mais je te fais confiance :-*) */
        double gaussrand();
        double cnd_manual(double x);    
        /* Il y a peut être d'autres choses sympa à prévoir ;-) */
    private:
        /* une fonction (à usage interne uniquement) qui s'occupe de calculer la moyenne */
        void calculerMoyenne(); // à implémenter :D
        /* une fonction (à usage interne uniquement) qui s'occupe de calculer l'écart-type */
        void calculerEcartType(); // à implémenter
        std::vector<double> lesValeurs_; // Toutes les valeurs utilisées pour calculer la 
                                         // moyenne et l'écart-type
        double moyenne_;
        double ecart_type_;
    };
    A ce moment là, tu pourras effectivement dire que tu respecte l'encapsulation, parce que tout le mécanisme qui permet de calculer la moyenne (ou l'écart-type) est directement pris en charge par la classe et que l'utilisateur ne peut faire qu'une chose pour les modifier : rajouter une valeur à celles qui sont utilisées pour le calcul.
    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 Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Dés lors, je me pose la question de savoir pourquoi tu te fais ch..er à placer la valeur moy en accessibilité privée et à rajouter ces deux fonctions si, d'une certaine manière, il aurait été beaucoup plus facile de placer moy dans l'accessibilité publique
    Il y a quand même au moins 2 cas où variable privée + get/set est préférable à une variable publique :
    Quand il y à des conditions
    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
    class Foo {
       int m_val;
    public:
       int getVal() const { return m_val; }
       void setVal(int v) {
          if(v < 2) throw exception("v < 2");
          m_val = v;
       }
       // et eventuellement 
       bool trySetVal(int v) {
           if(v < 2) return false;
           m_val = v;
           return true:
       }
    };
    Et pour "harmoniser" l'utilisation d'une classe : avoir que des fonctions.

    Mais pour tout le reste tu as raison.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Il y a quand même au moins 2 cas où variable privée + get/set est préférable à une variable publique :
    En fait, j'aurais du écrire :

    "Si c'est pour te faire ch..er <snip> !... Sauf que (la suite répond justement au code que tu présentes )"
    Quand il y à des conditions
    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
    class Foo {
       int m_val;
    public:
       int getVal() const { return m_val; }
       void setVal(int v) {
          if(v < 2) throw exception("v < 2");
          m_val = v;
       }
       // et eventuellement 
       bool trySetVal(int v) {
           if(v < 2) return false;
           m_val = v;
           return true:
       }
    };
    Le problème de cette fonction est tout à fait le même que celui auquel tu seras confronté avec une variable publique :

    Tu rends l'utilisateur de la classe responsable de la mise en place de toute la logique qui permet de déterminer la valeur attendue.

    Le résultat, c'est que tu perds littéralement le contrôle de la "localisation" de cette logique dans ton code et que du coup, la moindre tentative de modification au niveau de ta classe aura un impact impossible à chiffrer :

    Avec un peu de chance, l'utilisateur de la classe aura "bien travaillé" et centralisé la logique en un seul point du code. Mais, vu que Murphy sera de la partie, tu peux t'attendre à ce que cette logique soit dupliquée (sans doute plusieurs fois) et disséminée aux quatre coins du projet.

    Tu ne peux donc pas rendre la variable publique alors que ce serait tellement plus facile, mais tu ne peux pas d'avantage te contenter d'exposer une fonction qui permette de définir la valeur, qu'elle fasse une vérification ou non.

    Ce que tu dois exposer, c'est une (voire plusieurs) fonctions qui prenn(ent) en argument la (les) valeur(s) utile(s) et nécessaire(s) afin, non seulement d'effectuer la vérification, mais également de déterminer la nouvelle valeur à prendre en compte
    Et pour "harmoniser" l'utilisation d'une classe : avoir que des fonctions.
    Ben, comme au final, on en arrive à "tu aurais plus facile, mais tu peux pas", cet argument tombe tout seul
    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. error : 'tr' was not declared in this scope
    Par jimaitou dans le forum Débuter
    Réponses: 3
    Dernier message: 13/05/2009, 13h54
  2. getaddrinfo was not declared in this scope ?
    Par dr.c0der_ dans le forum C
    Réponses: 2
    Dernier message: 30/04/2009, 02h14
  3. QFormLayout was not declared in this scope
    Par kronos85 dans le forum Débuter
    Réponses: 5
    Dernier message: 11/12/2008, 02h30
  4. Réponses: 3
    Dernier message: 03/06/2007, 15h29

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