[conception] soucis sur un singleton
Bonjour tout le monde,
je viens d'implémenter un petit logger super simple (et trés spécifique à mon appli, c'est pourquoi je ne peux pas utiliser des logger existants). Etant donné que je ne dois en avoir qu'un dans toute mon appli, j'ai estimé qu'il était légitime d'en faire un singleton.
Voici, en gros, à quoi ressemble mon logger:
Code:
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
| /// Logger.h
// includes et autres
class Logger : public std::ofstream
{
public:
static void Init(std::string filename)
{
if ( m_pInstance == NULL )
{
m_pInstance = new Logger(filename);
// ici, du code relatif à l'initialisation du logger
}
}
static Logger& GetInstance()
{
if ( m_pInstance == NULL )
{
m_pInstance = new Logger();
}
return *m_pInstance;
}
// destructor (bon, en réalité, le destructeur est privé)
~CLogger(){close();}
private:
// constructor
Logger(std::string filename = "c:/temp/log.txt")
: std::ofstream( filename.c_str(), std::ios::app )
{}
// unique Logger instance
static CLogger* m_pInstance;
}; |
Je déclare et j'initialise le singleton dans Logger.cpp
Code:
1 2 3 4
| ///Logger.cpp
#include "CLogger.h"
CLogger* CLogger::m_pInstance = NULL; |
Bon, mon code fonctionne, mais j'ai 2 problèmes:
1/ J'aimerais forcer l'utilisateur de cette classe à initialiser le logger. En gros, j'aurais aimé faire en sorte que si Logger::Init(monfichier); n'est pas appelé, ça génère une erreur à la compilation.
Mais je ne vois vraiment pas comment faire. Est-ce seulement possible?
2/ J'utilise un outil d'analyse de code qui me hurle dessus à la ligne:
Code:
CLogger* CLogger::m_pInstance = NULL;
En gros, il me dit: "This non-local object will be initialised at runtime."
Et il me dit d'aller voir l'item #47 du livre "Effective C++, 2nd edition" de Scott Meyers.
Ce que j'ai fais. Et je ne suis pas plus avancé, car j'ai l'impression que mon implémentation est fidèle aux conseils du livre.
Voyez-vous où est mon erreur?
note: afin de simplifier l'utilisation de ce logger, j'ai défini les macros suivantes:
Code:
1 2
| #define LOG(X) CLogger::GetInstance() << X << std::endl
#define INIT_LOG(X) CLogger::Init(X) |
Ce qui me permet de l'utiliser ainsi:
Code:
1 2
| INIT_LOG("c:/temp/log.txt");
LOG( "test " << 1234 << UnObjet << std::endl ); |