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 :

Problème de link dans un singleton


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut Problème de link dans un singleton
    Bonjour,

    voici une implémentation du singleton :
    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
    {
            private: static T instance;
            private: Singleton()
            {
            };
            private: Singleton(const T&);
            private: T& operator=(const T&);
            public: static T& getInstance()
            {
                    return instance;
            }
    };
    int main(void)
    {
            int& n1 = Singleton<int>::getInstance();
            return 0;
    }
    Mais le link génère l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /tmp/ccWMzoqa.o: In function `Singleton<int>::getInstance()':
    test.cpp:(.text._ZN9SingletonIiE11getInstanceEv[Singleton<int>::getInstance()]+0x4): undefined reference to `Singleton<int>::instance'
    Où est l'erreur ?

    Merci .

  2. #2
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    Bon alors il y a quand même certaines choses choquante dans ton code, premièrement pourquoi définir private et public devant toutes tes fonctions? Par défaut une classe est en private donc change seulement pour public quand tu en as besoin.

    Ensuite toute données statiques doivent être initialisées!

    Aussi, tu définis comme donnée ce qui signifie que instance ne sera pas une instance mais dans ton exemple un int

    Maintenant voila un code qui compile :
    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
    template<typename T>
    class Singleton
    {
    	static T *instance;
     
    	Singleton()
    	{
    	};
     
    	Singleton(const T&);
    	T& operator=(const T&);
     
    public:
    	static T& getInstance()
    	{
    			return *instance;
    	}
    };
     
    template<typename T> T*Singleton<T>::instance = 0;
     
    int main(void)
    {
            int& n1 = Singleton<int>::getInstance();
            return 0;
    }
    Quand bien même ce code compile il ne s'exécutera pas correctement puisque la valeur pointée par instance n'est pas définis... Mais je suppose que tu n'as pas finis la classe singleton...

  3. #3
    screetch
    Invité(e)
    Par défaut
    il est possible de stocker un T dans la classe singleton.

    ce qui manque c'est juste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<typename T> T Singleton<T>::instance;

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Par défaut
    Si tu veux faire un singleton automatique, tu utilise un constructeur public :
    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
     
    template<typename T>
    class singleton
    {
        static T* instance;
     
    public:
        singleton() // avec une classe T qui dérive de singleton<T>
        {
            if(instance != 0) throw "le singleton existe déjà";
            else instance = dynamic_cast<T>(this);
        }
     
        singleton(T &val) // avec des objets T qui ne dérivent pas de singleton T (comme les types de base)
        {
            if(instance != 0) throw "le singleton existe déjà";
            else instance = &val;
        }
     
    private:
        singleton(const singleton &) {}
        singleton &operator=(const singleton &) {}
     
    public:
        ~singleton()
        {
            instance = 0;
        }
     
        static T* get() { return instance; }
        static void set(T &val) { instance = &val };
    };
    Je préfère cette solution là (plus automatisée).

    J'ai eu un problème avec 'static T* instance" (le compilateur n'en voulait pas) donc j'ai fabriqué une petite classe qui s'occupe du stockage :
    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
    template<typename T>
    class locker
    {
        T* _val;
        bool _full;
     
    public:
        locker(): _val(0), _full(false) {}
        locker(const T &val): _val(val), _full(true) {}
        ~locker() {}
     
        inline locker &operator=(T* val) { _val = val; _full = (val != 0); }
        inline T* operator T*() { return _val; }
        inline T* const get() { return _val; }
        inline bool full() const { return _full; }
    };
    et je remplace 'static T* instance;' par 'static locker<T> instance;' et le compilateur est content.

  5. #5
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    En effet il y a des erreurs de conception : un singleton embarque une instance de lui-même et pas le type "T".

    Voici une version sans cette erreur, avec l'instance unique dans la méthode"getInstance", qui compile :
    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
    template<typename T>
    class Singleton
    {
            private: Singleton<T>()
            {
            };
            private: Singleton<T>(const Singleton<T>&);
            private: Singleton<T>& operator=(const Singleton<T>&);
            public: static Singleton<T>& getInstance()
            {
                    static Singleton<T> instance;
     
                    return instance;
            }
    };
    Mais :
    1) pourquoi ceci ne compile pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template<typename T>
    class Singleton
    {
            private: static Singleton<T> instance;
            private: Singleton<T>()
            {
            };
            private: Singleton<T>(const Singleton<T>&);
            private: Singleton<T>& operator=(const Singleton<T>&);
            public: static Singleton<T>& getInstance()
            {
                    return instance;
            }
    };
    ?
    2) Comment embarquer l'instance unique en tant qu'attribut de la classe si cela est possible ?

    Merci .

  6. #6
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par screetch Voir le message
    il est possible de stocker un T dans la classe singleton.

    ce qui manque c'est juste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<typename T> T Singleton<T>::instance;

  7. #7
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    A quel endroit faut il placer ce code s'il te plait :
    - en tant que définition d'attribut
    - en tant que retour de la fonction "getInstance"
    - ... ?

    Aucune des deux solutions citées ne compilant pour l'instant .

    En te remerciant de ta patience .

  8. #8
    screetch
    Invité(e)
    Par défaut
    sur une ligne a elle toute seule

    quand tu ecris

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class A
    {
      static A* instance;
      A* getInstance();
    };
    ce que tu fais c'est dire que la classe A contient une instance A et une fonction getInstance();, ce que l'on appelle une declaration. Cela indique au compilateur que tu vas mettre quelque art ces choses la, qu'elles existent.

    Ensuite, tu dois en donner la definition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    A* A::getInstance()
    {
      return instance;
    }
    cela tu le connais, c'est la definition de la methode, comme tu as dit au compilateur, voila, tu ne mens pas : voila cette fonction.

    C'est pareil pour le static, tu dois le definir quelque part, comme les methodes, en ajoutant une ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type classe::variable (= valeur)
    la valeur est optionnelle.

    pour A, cela ressemble donc a voila la definition de la variable A.

    Enfin, comme tu travailles avec les templates, comme avec les methodes, la definition doit etre visible par le compilateur donc au lieu de la mettre dans un fichier C++ tu dois la mettre dans un fichier en-tete (.h)

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

Discussions similaires

  1. Problème de link dans une application c++/CLI
    Par moooona dans le forum C++/CLI
    Réponses: 3
    Dernier message: 09/01/2012, 10h01
  2. Réponses: 0
    Dernier message: 01/03/2009, 14h44
  3. Problème conc. <html:link> dans Struts
    Par Chavadam dans le forum Struts 1
    Réponses: 3
    Dernier message: 26/02/2009, 08h44
  4. Problème au link : librairie dans une librairie
    Par jbwan dans le forum VC++ .NET
    Réponses: 0
    Dernier message: 15/04/2008, 15h10
  5. Réponses: 7
    Dernier message: 22/06/2007, 10h56

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