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 :

Mon Singleton est-il correct ?


Sujet :

C++

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut Mon Singleton est-il correct ?
    Bonjour,

    dans une appli A1, je dois mettre des infos en mémoire partagée, qui seront utilisées par une autre appli A2.
    Donc pour ça j'ai fait une classe CSharedMemory. Pas de pb.

    Dans cette appli A1, je sais donc que je dois utiliser un objet "global" CSharedMemory, et aprés avoir utilisé "extern" que je trouvais un peu pourri, et en voyant l'exeple de la faq sur le Singleton, je me suis dit pourquoi pas l'utiliser.

    Est-ce correct ?

    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
     
    class CGlobal
    {
     
    private :
    	CSharedMemory sm;
     
    	//Constructeur privé
        CGlobal() :
    		sm(1000, "SM_TDELTA") {
    	}
     
    public :
    	//Fonction static pour appeler notre seul objet CSharedMemory
    	static CSharedMemory& GetSharedMemory();
    };
     
     
    CSharedMemory& CGlobal::GetSharedMemory()
    {
    	static CGlobal glob;
    	return glob.sm;
    }
    Je compte utliiser cette classe CGlobal pour y mettre d'autres objets utilisés encore auourd'hui en "extern"

    Merci par avance.
    @+

  2. #2
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Il faut également que tu déclares le constructeur de copie et l'opérateur d'affectation en privé, sinon il y aura possibilité de dupliquer ton objet. Pas la peine de les définir par contre.

    EDIT : j'avais aps fait attention, là c'est ton CGlobal qui est un singleton, pas CSharedMemory.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    EDIT : j'avais aps fait attention, là c'est ton CGlobal qui est un singleton, pas CSharedMemory.
    Ben oui, c'est sûr que ça empeche personne de redéclarer un CSharedMemory,
    mais ce que je voulais c'est + de propreté qu'un extern pour mes objets globaux ...

  4. #4
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Citation Envoyé par olive_le_malin
    Ben oui, c'est sûr que ça empeche personne de redéclarer un CSharedMemory,
    mais ce que je voulais c'est + de propreté qu'un extern pour mes objets globaux ...
    Ok pas de souci alors, c'est le commentaire de la méthode GetCSharedMemory qui m'a induit en erreur :p

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Par contre si tu veux gérer plusieurs variables tu ne pourras plus déclarer ton instance de CGlobal en static dans les fonctions. A moins de faire une fonction unique GetGlobals() qui renvoie l'instance unique de CGlobal, puis de faire des accesseurs classiques pour accéder à ses diverses données membres.

    Attention aussi à la durée de vie de tes objets : avec une instance statique tu ne contrôles pas la destruction de ton singleton, et donc de ses données membres.

    Je plussoie aussi sur l'opérateur = et le constructeur par copie privés non définis. Sinon ton singleton sera bancal.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    La conception n'est pas claire. Dans ce cas, ça marchera parce qu'il n'y a qu'une seule fonction membre de CGlobal qui peut être utilisée et que c'est dans cette fonction que le l'instance unique de CGlobal est créée. Mais que se passera-t-til s'il y en a deux ?

    En fait, ta solution est à cheval entre deux modèles de conception. Celui d'une classe 'singleton' et celui d'une classe non-instanciable qui ne regroupe que des variable 'statiques'.

    Le premier modèle correspond à ceci :
    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
     
    class CGlobal
    {
    public:
      // accès au singleton
      CGlobal& instance() {
        static CGlobal sf_instance;
        return sf_instance;
      }  
     
      Ressource1& ressource1() {
        return ressource1_;
     }
     
      Ressource2& ressource2() {
        return ressource2_;
     }
     
    protected:
      CGlobal() {
        /* init des variables membre */
      }
     
    private:
      Ressource1 ressource1_;
      Ressource2 ressource2_;
     
      // Interdiction des copies
      CGlobal(const CGlobal& other);
      CGlobal& operator=(const CGlobal& other);
    };
    ...
    /* Accès à une ressource */
    CGlobal::instance().ressource1();

    le second modèle :
    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
     
    class CGlobal
    {
    public:
      static Ressource1& ressource1() {
        static Ressource1 sf_ressource1;
        return ressource1;
     }
     
      static Ressource2& ressource2() {
        static Ressource2 sf_ressource2;
        return ressource2;
     }
    private:
      CGlobal(); // Classe non instanciable
    };
     
    // Accès à une ressource
    CGlobal()::ressource1();
    Méler les deux me semble bancal

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    Bonjour,
    merci pour vos réponses.

    Il faut également que tu déclares le constructeur de copie et l'opérateur d'affectation en privé, sinon il y aura possibilité de dupliquer ton objet. Pas la peine de les définir par contre.
    Je plussoie aussi sur l'opérateur = et le constructeur par copie privés non définis. Sinon ton singleton sera bancal.
    OK, je vais le faire

    Par contre, je comprends pas ça :
    Par contre si tu veux gérer plusieurs variables tu ne pourras plus déclarer ton instance de CGlobal en static dans les fonctions. A moins de faire une fonction unique GetGlobals() qui renvoie l'instance unique de CGlobal, puis de faire des accesseurs classiques pour accéder à ses diverses données membres.
    Puisque là je renvoie un accesseur à ma variable membre privée CSharedMemory, qu'est ce qui m'empêche de le faire pour les autres ?

    @+

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par olive_le_malin
    Par contre, je comprends pas ça :
    Puisque là je renvoie un accesseur à ma variable membre privée CSharedMemory, qu'est ce qui m'empêche de le faire pour les autres ?
    Singleton = une seule instance de la classe CGlobal.
    Si je suis ton modèle, avec 2 ressources cela donne ça
    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
     
    class CGlobal
    {
     
    private :
    	CSharedMemory sm;
            CRessource ressource;
     
       //Constructeur privé
        CGlobal() : sm(1000, "SM_TDELTA"), ressource(...)
            {
    	}
     
    public :
    	//Fonction static pour appeler notre seul objet CSharedMemory
    	static CSharedMemory& GetSharedMemory();
     
    	//Fonction static pour appeler notre seul Ressource
    	static CSharedMemory& GetRessource();
     
    };
     
     
    CSharedMemory& CGlobal::GetSharedMemory()
    {
    	static CGlobal glob; // <--- Création d'une instance de CGlobal
    	return glob.sm;
    }
     
    CSharedMemory& CGlobal::GetRessource()
    {
    	static CGlobal glob; // <--- Création d'une instance de CGlobal
    	return glob.ressource;
    }
    Ce qui pose beaucoup de soucis, puisque deux instance de CGlobal sont créées.
    Cela implique que le constructeur de CGlobal sera appelé 2 fois, donc 2 instances de Ressource et CSharedMemory seront initialisées.
    Si ma deuxième ressource nécéssite des ressources uniques (socket sur une adresse IP par exemple), les conséquences sont désastreuses.

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    Pauvre de moi, exact !!!
    Merci ... ce fut trés clair !

    Effectivement, sans l'écrire avec Plusieurs variables membres, je l'avais pas vu !

    Je vais donc arranger ça comme il faut.

    Par contre, Et il est vrai que ce que je veux faire correspond peut être mieux au second modele décrit par Jan Rendeck.

    Merci beaucoup

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    Re-bonjour,
    une dernière question :

    par rapport au premier modèle donné par Jan Rendeck :
    ne serait-il pas mieux d'écrire :

    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
     
    class CGlobal
    {
    private :
      // accès au singleton
      static CGlobal& instance() {
        static CGlobal sf_instance;
        return sf_instance;
      }  
     
    public:
      static Ressource1& ressource1() {
        return instance().ressource1_;
     }
     
      static Ressource2& ressource2() {
        return instance().ressource2_;
     }
     
    protected:
      CGlobal() {
        /* init des variables membre */
      }
     
    private:
      Ressource1 ressource1_;
      Ressource2 ressource2_;
     
      // Interdiction des copies
      CGlobal(const CGlobal& other);
      CGlobal& operator=(const CGlobal& other);
    };
    ...
    /* Accès à une ressource */
    CGlobal::ressource1();
    CGlobal::ressource2();
    De ce fait on simplifie la notation à l'utilisation, non ?

    @+

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Ce n'est pas plus simple, AMA. Tu mélanges une fois encore les 2 méthodes.
    Si les méthodes ressource1() et ressource2() sont 'static', quelle est l'utilité de l'instance unique de la classe CGlobal ?
    Dans ce cas, il faut mieux utiliser une classe non-instanciable pour regrouper l'ensemble de ces fonctions et variables comme je l'expose dans mon précédent message.

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    Citation Envoyé par Jan Rendek
    Si les méthodes ressource1() et ressource2() sont 'static', quelle est l'utilité de l'instance unique de la classe CGlobal ?
    Et ouais c'est vrai, il n'y en a pas ...

    Merci

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

Discussions similaires

  1. mon XSD est il correct ?
    Par shanks1o dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 17/02/2012, 20h23
  2. [MCD] Mon script est-il correct ?
    Par batchi dans le forum Schéma
    Réponses: 1
    Dernier message: 16/02/2011, 15h50
  3. Mon script est-il correcte ?
    Par neufrdb dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 01/02/2011, 11h13
  4. Réponses: 5
    Dernier message: 10/11/2007, 10h20
  5. Mon formulaire est-il correct?
    Par biglittlekiss dans le forum Langage
    Réponses: 3
    Dernier message: 26/11/2006, 12h29

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