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 :

difficultés sur un singleton: variable membre indéfinie


Sujet :

Langage C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 114
    Points : 53
    Points
    53
    Par défaut difficultés sur un singleton: variable membre indéfinie
    Bonjour,
    je crois que c'est un cas d'école mais je n'arrive pas à résoudre.

    Fraichement converti aux classes,
    j'ai créée avec succés des classes et des singletons, ça a été laborieux mais ça fonctionne (merci à ceux qui m'ont guider)

    Je veux créer un singleton supplémentaire aujourd'hui, mais ça ne fonctionne plus, pourtant basé sur mes succés précédent et, je croyais, une bonne compréhension des notions private/public et static

    Voyez-vous où se situe la ou les erreurs?

    mask.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
    17
    18
    19
    20
    21
    22
    #ifndef MASK_H
    #define MASK_H
    #include <opencv2/opencv.hpp>
    class mask {
      static int aaaaa;
      static cv::Mat imgMask[10]; //tableau de 10 cv::Mat (images)
      static bool matMask[640][480];  //matrice de masquage
     
      private:  // constructeur et destructeur en private car singleton (une seule instanciation de la classe)
        mask(){};
        ~mask(){};
     
      public:
        static mask *getInstance(); //demande d'instanciation
        static void kill ();  //destruction de l'instanciation
        static int get_aaaa(void);
        static void acqImageMask (cv::VideoCapture& flux);
     
      private:
        static mask *singleton;  //
    };
    #endif
    mask.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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include "mask.h"
    /*****************************/
    /* instanciation du singleton */
    /********************************/
    mask *mask::getInstance(){
      if (NULL==singleton){
        singleton = new mask;  //check si déjà instancié
        aaaaa++;
        }
      return singleton;
    }
    /*******************/
    /* kill le singhleton */
    /*********************/
    void mask::kill(){
      if (NULL!=singleton){
        delete singleton;
        singleton = NULL;
        aaaaa--;
      }
    }
    /*********************************/
    /*  retourne le nombre do'bjets instanciés */
    /********************/
    int mask::get_aaaa(void){return aaaaa;}
    /**********************************/
    /* appelle la capture d'une image non conservée (vidage buffer) */
    /*********************************/
    void mask::acqImageMask(cv::VideoCapture& flux){
      if (flux.read(imgMask[0])){
      std::cout << "succés "<<std::endl;
        }
      else{
        }
    }
    compil:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /............../mask.cpp|11|référence indéfinie vers « mask::singleton »|
    idem pour aaaaa

    Merci bien

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    À ajouter dans ton .cpp:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int mask::aaaaa;
    cv::Mat mask::imgMask[10]; //tableau de 10 cv::Mat (images)
    bool mask::matMask[640][480];  //matrice de masquage
    mask *mask::singleton;
    (Les définitions de chaque variable statique déclarée dans ta classe)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Il te faut définir les variables statiques au sein de l'unité de compilation, en ajoutant au .cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    mask *mask::singleton;
    int mask::aaaaa;
     
    ...

  4. #4
    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
    Une variable static doit être initialisée. Donc quelque part tu dois avoir mask* mask::singleton = nullptr; (pour chaque static que tu as)
    Cela dit, un singleton c'est rarement une bonne chose, et si tu fais une bidouille spécifique pour chacun t'es pas couché
    Un singleton c'est un pattern bien défini, quelque chose comme (non testé)
    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
    template<class T>
    class Singleton
    {
    public:
      static bool exists() { return sInstance != nullptr; }
      static T& get() {
        if (!exists())
            create();
        return *sInstance.get();
      }
      static void release() { sInstance = nullptr; }
    protected:
      Singleton() = default;
      virtual ~Singleton() = default;
     
    private:
      void create() { sInstance = std::make_unique<T>(); }
      static std::unique_ptr<T> sInstance;
    };
    template<class T>
    std::unique_ptr<T> Singleton::sInstance;
     
    class MaClass : public Singleton<MaClass> {
    public:
      void toto() {}
    };
    int main() {
      MaClass::get().toto();
    }
    Sinon on peut tout simplement faire en sorte que le programme ne crée une instance qu'une fois (et donc contrôler où et quand la création se passe) et permettre son accès de partout (un genre de global camouflée - également non testé)
    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
    template<class T>
    class Singleton
    {
    public:
      static bool exists() { return sInstance != nullptr; }
      static T& get() { assert(exists()); return *sInstance; }
    protected:
      Singleton() {
        assert(sInstance == nullptr);
        sInstance = static_cast<T*>(this);
      }
      virtual ~Singleton() {
        assert(sInstance == this);
        sInstance = nullptr;
      }
     
    private:
      static T* sIntance;
    };
    template<class T>
    T* Singleton::sInstance = nullptr;
     
    class MaClass : public Singleton<MaClass> {
    public:
      void toto() {}
    };
    int main()
    {
      MaClass maclass;
      MaClass::get().toto();
    }
    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.

  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
    Salut,

    Note au passage que l'on peut se faciliter singulièrement la vie pour la définition d'un singleton en C++...

    il suffit d'un
    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
    template <typename T>
    class Singleton{
    public:
        /* parce qu'on n'en veut pas de copie
         */
        Singleton(Singleton const &)=delete;
        Singleton& operator= (Singleton const & )=delete;
        T& instance(){
            static T inst;
            return inst;
        }
    protected:
        /* pour que seules les classes dérivée puisse appeler le constructeur 
         * et le destructeur
         * de singleton
         */
        Singleton() = default;
        ~Singleton() = default;
    };
    C'est thread-safe, et ca évites bien des soucis liés à l'utilisation de pointeurs ou fiasco d'initialisation des variables statiques

    EDIT: Mais bon, le singleton, en tant que patron de conception est une véritable calamité conceptuelle, et l'idéal est toujours de s'en passer si on peut faire autrement...
    (et l'expérience tend à démontrer que l'on peut très souvent faire autrement )
    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
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    En complément de ces "ne fais pas de singleton", il faut te poser une question essentielle pour décider si le singleton est la solution à ton problème : veux-tu garantir de n'avoir qu'une et une seule instance (== en avoir 2 mettrait en danger ton application) ou veux-tu avoir une manière simple d'obtenir une instance d'une classe ? Souvent, on est dans le 2e cas mais le patron Singleton est fait pour le 1er cas.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 114
    Points : 53
    Points
    53
    Par défaut
    Merci bien à vous tous,

    dans l'urgence, j'ai choisi la solution de Médinoc et Mat_Houston.
    il est vrai que c'était ainsi pour mes autres singletons.

    Bousk et Koala, vos propositions me demandent un peu de temps pour les intégrer.

    A l'origine mon appli était extrêmement mal codée, c++ mais façon C, et plein de la variables globales, .... plein de trucs moches.
    J'ai fait mes premiers pas en C++, je suis assez content du boulot, mais je vois bien que je ne réfléchi pas encore naturellement en mode C++.
    J'espère avoir d'autres rapidement pour ne pas relacher l'effort maintenant.

    Pour répondre à Bktero, avec mes mots, mon objectif est de n'avoir qu'un objet Mask.

    Merci encore

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

Discussions similaires

  1. pointeur sur variable membre
    Par hdgetnet dans le forum Débuter
    Réponses: 10
    Dernier message: 30/07/2010, 14h49
  2. Etat basé sur requête à champs variables
    Par hmonnet dans le forum Access
    Réponses: 2
    Dernier message: 10/11/2005, 08h19
  3. Réponses: 5
    Dernier message: 19/09/2005, 20h58
  4. Réponses: 6
    Dernier message: 06/10/2004, 12h59

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