Singleton

Soyez le premier à donner votre avis sur cette source.

Snippet vu 5 845 fois - Téléchargée 29 fois

Contenu du snippet

Ce code implémente, a travers d une classe template, un classe de singleton, qui permet de n utiliser qu une seule instance d une classe particulière.
Le code est largement réutilisable, et peut s avérer utile dans certains cas, c est pourquoi je le mets a disposition

Source / Exemple :


#include <stdio.h>

#define DEBUG	// affiche les informations de debuggage

template <typename T> 
class singleton 
{ 
protected: 
    // Constructeur/Destructeur 
    singleton( ) { } 
	// Supprime l instance de la classe si elle a été crée
    ~singleton( ) 
	{
		if( m_pInstance != NULL ) 
        { 
            delete m_pInstance; 
            m_pInstance = 0; 
        } 
	} 

public: 
    // renvoie une instance de la classe, la crée si elle n existe pas
    static T *GetInstance( void ) 
    { 
        if( m_pInstance == NULL ) 
		{
			m_pInstance = new T; 
#ifdef DEBUG
			printf ("Creation de objet\n");
#endif
		}
		else
		{
#ifdef DEBUG 
			printf ("Objet deja cree\n");
#endif
		}
		
        return ((T *)m_pInstance); 
    } 

private: 
    static T    *m_pInstance;	// instance unique de la classe

}; 

template <typename T> T *singleton<T>::m_pInstance = NULL;

// on derive la classe pour obtenir ses methodes
class CTest : public singleton<CTest> 
{ 
    friend class singleton<CTest>; // necessaire pour acceder aux variables privees

public: 
    // fonctions publiques 
    void    Set( int _a ) { a = _a; } 
    int     Get( ) { return a; } 

private: 
    // variable membre 
    int     a; 

};

// Fonction principale
int main( int argc, char *argv[] ) 
{ 
    CTest *a, *b;	// inconvénient :: on doit utiliser des pointeurs

	// recupere une instance de la classe, peu importe si elle a été créée ou pas
	a = CTest :: GetInstance ();
	b = CTest :: GetInstance ();

    a->Set( 3 ); 

    // affichage des valeurs
    printf( "a->a = %d\n", a->Get( ));
    printf( "b->a = %d\n", b->Get( ));
    return 0; 
}

Conclusion :


Ben voila, le code marche plutot bien, j espere l avoir assez commenté, n hésitez pas a posez les questions qui vous traversent l esprit a propos de cette source, je me fereais une joie d y répondre ;)
A+

A voir également

Ajouter un commentaire

Commentaires

Messages postés
173
Date d'inscription
jeudi 20 décembre 2001
Statut
Membre
Dernière intervention
22 août 2008

Lut
Par rapport a la remarque concernant iostream et stdio, c est une question de gout, personnellement ca ne me dérange absolument pas de faire des printf dans quelque chose fait en c++ (et qui ne peut, comme ici, pas etre porté vers du c (du moins je ne crois pas))
La remarque concernant le renvoie d une variable statique au l ieu d utiliser une methode statique me semble meilleure, je vais garder celle la. Néanmoins cette version portera probleme lors de l utilisation du multi threading (pas dans mon cas, car je ne m en sers pas), je ne sais pas si les methodes statiques sont sources de problemes si elles sont utilisées en multithreading
Et juste une question relative aux templates : qu elle est la difference entre
template < class T > class truc {....}; et
template < typename T > class truc {....}; ?
Car bien que je me serve des template depuis un moment, je n ai pas vraiment saisi la différence ....
A+
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
BlackGoddess:
class Singleton
{ public: static Singleton& Instance(); };
// Il faut mettre les constructeurs en privé ici

Singleton& Singleton::Instance() {
static Singleton s;
return s;
}
Il faut utiliser de préférence une méthode statique de classe, cela
permet d'éviter des problèmes sur l'ordre de création des singletions.
Cette version doit marcher dans les cas simples.
(C'est la version de Scott Meyers sauf erreur de ma part)
La version postée utilise les templates qui est une forme un peu plus avancée
pour les singletons qui permettrait de gérer par les références mortes,
le multi-thread par exemple.
Messages postés
3006
Date d'inscription
dimanche 14 avril 2002
Statut
Membre
Dernière intervention
31 décembre 2008

BlackGoddess, je suis pas tt à fait sûr que ton option fonctionne dans le cas où tu voudrais utiliser proprement le singleton dans des classes sensées être réutilisables, si? je sais pas trop, mais ça me paraît trop simple (c'est pas un critère évidemment...)
Messages postés
338
Date d'inscription
jeudi 22 août 2002
Statut
Membre
Dernière intervention
14 juin 2005

juste pour info :

#include <stdio.h> est un header C
#include est l'equivalent C+
printf est du C, cout est du C++

on ne peut pas utiliser ca pour un singleton ? :

class singleton
{
...
};

class utilise_singleton
{
static singleton s;
...
};

static utilise_singleton::singleton s;
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
Salut,
quelques remarques...
Ta classe ressemble plus à un conteneur
de singleton qu'à un singleton (cf Modern C++ Design)
Si tu ajoutes { CTest c = *a; }
après b = CTest :: GetInstance ();
ton programme ne devrait pas fonctionner (core)
Voici une version sans pointeur :

// ----- SingletonHolder
template< typename T >
class SingletonHolder
{
protected:
SingletonHolder();
SingletonHolder( const SingletonHolder& );
~SingletonHolder() { delete instance_; }
SingletonHolder& operator == ( const SingletonHolder& );

static T* instance_;

public:
static T& Instance();
};

template< typename T >
T& SingletonHolder<T>::Instance()
{
if ( !instance_ )
instance_ = new T;

return *instance_;
}

template< typename T >
T* SingletonHolder<T>::instance_ = 0;


// Fonction principale
int main( int argc, char *argv[] )
{
CTest& a = SingletonHolder< CTest >::Instance(),
& b = SingletonHolder< CTest >::Instance();

... idem pour la suite
}

C'est du rapidement fait, ton y'a peut être d'autres bugs.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.