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 :

Appel méthode static


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2012
    Messages : 83
    Points : 87
    Points
    87
    Par défaut Appel méthode static
    Bonsoir à tous,

    je m'arrache les cheveux depuis un moment sur un problème que je ne parviens pas à résoudre. Impossible d'appeler une méthode static. Voici le code:

    test.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <iostream>
    #include "Personne.h"
     
    int main() {
     
        Personne::add() ;
        std::cout << "Test." ;
     
        return 0 ;
    }
    Personne.h
    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
    #ifndef PERSONNE_H
    #define	PERSONNE_H
     
    #include <vector>
     
    class Personne {
     
        public:
     
            Personne () ;
            ~Personne() ;
            static void add() ;     
            static std::vector<Personne> list ;
    } ;
     
    #endif	/* PERSONNE_H */
    Personne.cpp
    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
    #include <vector>
    #include <iostream>
    #include "Personne.h"
     
    using namespace std ;
     
        Personne::Personne () { 
        }
     
        Personne::~Personne () {
        }
     
        void Personne::add() {
     
            Personne a () ;
            //cout << list.size() ; => ERREUR
            //list.push_back(a) ; => ERREUR
            //cout << list.size() ; => ERREUR
        }
    Chacune des 3 lignes sous commentaire du fichier Personne.cpp produisent une erreur à la compilation. A savoir BUILD FAILED (exit value 2, total time: 4s)

    Si quelqu'un pouvait m'expliquer pourquoi il m'enlèverait une gênante épine du pied !
    Merci de m'avoir lu.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    ce code fonctionne très bien.
    Moyennant de l'écrire correctement : Personne a () ; déclare un prototype d'une méthode s'appelant a et qui retourné un Personne.
    Pour déclarer une variable a de type Personne il faut faire Personne a;
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    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,

    La première chose à savoir, c'est que les compilateurs C++ ont généralement tendance à être particulièrement verbeux.

    Lorsque tu es confronté à une erreur qui te dit simplement "compilation failed" (ou quelle que soit la forme similaire), il faut te dire que ce n'est qu'un "résumé" des problèmes qui ont été rencontrés.

    Il faut alors "remonter" dans la liste des messages afin de déterminer quelle erreur s'est réellement produite.

    Le "plus malin" est généralement de commencer par résoudre la toute première erreur, car il n'est pas rare que certaines erreurs soient dues "en cascade" au fait que le compilateur "perd les pédale" du fait d'une première erreur. En gros, il arrive régulièrement qu'en apportant une solution à la première erreur, tu arrives à résoudre un bon nombre des erreurs suivantes .

    Généralement, lorsque tu es confronté à une erreur de compilation, il est très utile pour ceux qui voudront t'aider d'indiquer les premières erreurs survenues. Cela aidera énormément les intervenants à savoir ce qui se passe et donc à t'apporter une aide efficace

    En un mot comme en cent : aide nous à t'aider, dans le cas présent en nous indiquant les erreurs auxquelles tu es confronté

    Ceci dit, la première erreur à laquelle tu es sans doute confronté est sans doute très proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: no matching function for call to ‘std::vector<Personne>::push_back(Personne (&)())
    Cette erreur est sans doute suivi d'un certain nombre d'informations qui peuvent paraître plus ou moins cryptiques comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    note: candidates are:|
    /usr/include/c++/4.8/bits/stl_vector.h|901|note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Personne; _Alloc = std::allocator<Personne>; std::vector<_Tp, _Alloc>::value_type = Personne]|
    /usr/include/c++/4.8/bits/stl_vector.h|901|note:   no known conversion for argument 1 from ‘Personne()’ to ‘const value_type& {aka const Personne&}’|
    /usr/include/c++/4.8/bits/stl_vector.h|919|note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Personne; _Alloc = std::allocator<Personne>; std::vector<_Tp, _Alloc>::value_type = Personne]|
    /usr/include/c++/4.8/bits/stl_vector.h|919|note:   no known conversion for argument 1 from ‘Personne()’ to ‘std::vector<Personne>::value_type&& {aka Personne&&}’|
    Comme les informations que ces lignes apportent ne te mettront sans doute pas sur la voie, il faut savoir que ton code
    ne fait absolument pas ce que tu crois.

    Tu crois créer une variable nomée a qui serait du type Personne He bien non, tu as tout faux.

    Lorsque le compilateur rencontre cette ligne de code, il estime que tu déclares une fonction nommée a qui ne prend aucun argument et qui renvoie un objet de type personne.

    Le message d'erreur et les informations qui suivent tentent de te faire comprendre que le compilateur ne sait pas comment convertir une fonction qui ne prend aucun argument et qui renvoie un objet de type Personne en un objet de type Personne

    Si l'erreur apparaît au niveau du push_back, c'est "simplement" parce que c'est à cet endroit particulier que le besoin de conversion se fait sentir ... Mais l'origine du problème se trouve bel et bien au niveau de la déclaration de la fonction qui devrait en réalité être une déclaration de variable
    La solution est donc de veiller à créer une variable de type Personne

    Et, pour ce faire, ben il s'agit de modifier ta ligne en
    Une nouvelle tentative de compilation va changer le message d'erreur qui ressemblera alors à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    référence indéfinie vers « Personne::list »|
    Quand tu obteins une erreur qui te parle de "référence indéfinie" (undefined reference to ... en anglais), ce n'est plus le compilateur qui parle, mais l'éditeur de liens.

    L'éditeur de liens est l'outil qui permet de regrouper les "parties de code" qui sont "disséminées dans différents fichiers objet" en un exécutable unique.

    Cette erreur te dis que l'éditeur de liens a trouvé une référence vers un symbole nommé "Personne::list" mais qu'il n'a trouvé nulle part la définition de ce symbole.

    Tu es parfaitement endroit de te demander pourquoi il ne trouve pas la définition de ce symbole, car, après tout, tu as bel et bien un membre de Personne qui correspond dans ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Personne {
     
        public:
     
            Personne () ;
            ~Personne() ;
            static void add() ;     
            static std::vector<Personne> list ;
    } ;
    Pour comprendre ce qui se passe, et sans entrer dans plus de détail que nécessaire, il faut comprendre que le mot clé static va avoir au minimum un effet particulier (du moins, un effet qui nous intéresse dans notre explication) : celui de faire que le membre list n'appartient à aucune instance spécifique de notre classe Personne.

    Ou, parce que l'on peut aussi voir cela dans l'autre sens, que toutes les instances de la classe Personne se partageront la même liste d'objets de type Personne.

    Il faut alors comprendre que les membres d'une classe sont tous créés (au travers du constructeur) au moment où l'on crée une instance particulière de la classe et qu'ils seront détruit au moment où l'instance particulière de la classe est détruite.

    Si on modifie un tout petit peu la classe Personne sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Personne {
     
        public:
     
            Personne () ;
            ~Personne() ;
            static void add() ;     
            static std::vector<Personne> list ;
            std::srtring name;
    } ;
    chaque fois que tu créeras une instance de la classe Personne, tu créeras un membre de type std::string qui sera identifiée par le nom "name" dans ton objet.

    Cela signifie que, si tu crées dix personnes, il y aura dix chaines de caractères identifiée par le nom name qui seront créées.

    Et, quand une instance est détruite, la chaine de caractères identifiée par le nom "name" de cette instance sera également détruite.

    Le problème, c'est que je viens de te dire que list n'appartient à aucune instance particulière de Personne et que toutes les instances de Personne vont se partager la même liste.

    La question devient alors : quelle instance de la classe Personne sera responsable de la création de ce membre list et, dans l'autre sens, quelle instance de la classe Personne devra s'occuper de détruire ce membre lorsqu'elle sera détruite

    On ne peut pas répondre à cette question car list doit exister avant que la première instance de Personne ne soit créée et doit continuer à exister même quand la dernière instance de Personne sera détruite.

    Finalement, le fait d'avoir déclaré le membre list comme étant un membre statique a pour résultat de créer une variable globale, bien qu'elle soit "enrobée" dans la notion de la classe Personne, mais le résultat est malgré tout là : list correspond bel et bien à une variable globale (ou du moins, est peu ou prou utilisable exactement comme une variable globale, bien que son utilisation ne soit possible qu'au travers des fonctions membres de la classe Personne).

    Il faut donc veiller à ce que cette variable globale soit effectivement créée en temps et en heure : au plus tard, avant de pouvoir accéder au contenu de la variable

    Pour ce faire, on va forcer la création de la variable, dans Personne.cpp, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Personne> Personne::list = std::vector<Personne>();
    Au final, le code de Personne.cpp ressemblera à 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
    #include <vector>
    #include <iostream>
    #include "Personne.h"
     
    //using namespace std ;
    std::vector<Personne> Personne::list = std::vector<Personne>();
        Personne::Personne () { 
        }
     
        Personne::~Personne () {
        }
     
        void Personne::add() {
     
            Personne a () ;
            cout << list.size() ; 
            list.push_back(a) ; 
            cout << list.size() ; 
        }
    Notes pour conclure que je ne suis absolument pas convaincu du bien-fondé d'une telle construction.

    Elle a en effet pour résultat de rendre la classe Personne responsable du maintient de la liste des personnes créées, ce qui n'est absolument pas cohérent :

    La classe Personne aura, très certainement, une responsabilité particulière, mais celle qui consiste à maintenir à jour la liste des personnes existante ne devrait pas lui échoir.

    Ca, c'est une responsabilité qui devrait échoir à "autre chose", comme un gestionnaire (bien que je n'aime pas trop ce terme, il ne m'en vient pas d'autre à l'esprit) de personne
    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

  4. #4
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2012
    Messages : 83
    Points : 87
    Points
    87
    Par défaut
    Un immense merci pour vos explications précises !

    Donc la déclaration des attributs statiques dans la classe n'alloue pas de mémoire tant que nous ne les déclarons pas en dehors ? (Contrairement au Java). C'est bien ça ?

  5. #5
    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 stoner Voir le message
    Un immense merci pour vos explications précises !

    Donc la déclaration des attributs statiques dans la classe n'alloue pas de mémoire tant que nous ne les déclarons pas en dehors ? (Contrairement au Java). C'est bien ça ?
    Ouaip, ca ne fait que déclarer une variable, sans forcément prévoir l'espace mémoire pour la stocker, en effet
    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

  6. #6
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    83
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2012
    Messages : 83
    Points : 87
    Points
    87
    Par défaut
    Super merci à vous !

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

Discussions similaires

  1. Appel méthode static/no static
    Par stefan73 dans le forum Débuter avec Java
    Réponses: 17
    Dernier message: 31/05/2012, 06h52
  2. Appel d'une méthode static dans un listener
    Par Faluchard dans le forum Langage
    Réponses: 4
    Dernier message: 23/08/2011, 11h39
  3. [1.x] [DOCTRINE] Problème appel méthode static
    Par Tyra3l dans le forum Symfony
    Réponses: 5
    Dernier message: 04/05/2011, 08h12
  4. Appel d'une méthode static d'une autre classe
    Par Mooneer dans le forum Langage
    Réponses: 2
    Dernier message: 30/01/2008, 19h05
  5. Débutante - Pb appel méthode static
    Par nmetais dans le forum Langage
    Réponses: 2
    Dernier message: 23/09/2005, 17h23

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