ofstream static en logging dans une bibliothèque
Bonjour,
Lors du développement d'une petite bibliothèque, je souhaite mettre en place un petit système de logging, et me suis heurté au problème suivant.
Précision: je voulais un petit truc simple, sinon, je sais , y'a boost::logging
http://torjo.com/log2/doc/html/index.html
Contraintes:
-je ne veux pas utiliser le flot standard stderr (via cerr), qui doit être réservé à l'appli principale (donc pas de freopen()...)
-je ne veux pas que l'ouverture de ce fichier se fasse via l'appel d'une fonction Start() ou un truc du genre. Il faut que le fichier s'ouvre "tout seul" dans toute application qui est linkée avec cette bibliothèque.
L'idée sur laquelle je suis parti est d'ajouter une classe A, contenant uniquement un attribut statique, déclaré en public, qui sera le ofstream qui servira pour logger des trucs. (bon, y'aura d'autres trucs, mais je limite à l'ECM)
Cette classe ne sera jamais instanciée (=> constructeur en private)
Code:
1 2 3 4 5 6 7 8
| // fichier a.hpp
class A
{
public:
static ofstream ferr;
private:
A() { assert(0); } // on sait jamais, avec les ordinateurs...
}; |
Code:
1 2 3
| // fichier a.cpp
#include "a.hpp"
ofstream A::ferr; |
L'idée, c'est que je puisse de partout faire:
Code:
A::ferr << "ici, y'a un problème\n";
Problème : comment faire en sorte que le fichier s'ouvre tout seul ?
La solution que j'ai trouvée: créer une classe parallèle, qui est instanciée aussi en static dans A, et dont le constructeur ouvre ferr:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class OuvreLog
{
OuvreLog()
{
A::ferr.open( "mon_log.txt" ); // plus la vérification kivabien, évidemment
A::ferr << "Hello\n";
}
~OuvreLog()
{
A::ferr << "bye\n";
A::ferr.close();
}
}; |
Mais si j'ajoute un membre statique de type OuvreLog dans la classe A, alors je tombe sur un problème de déclaration multiple:
- la classe OuvreLog a besoin de connaitre la classe A
- la classe A a besoin de connaitre la classe OuvreLog
Ma solution (pour l'instant): créer en statique dans A non pas un objet, mais un pointeur sur l'objet:
Code:
1 2 3 4 5 6 7 8 9
| // fichier a.hpp
class OuvreLog; // déclaration d'existence
class A
{
public:
static ofstream ferr;
static OuvreLog* ol;
}; |
et dans le .cpp, initialiser le pointeur en créant un objet:
Code:
1 2 3 4
| // fichier a.cpp
#include "a.hpp"
ofstream A::ferr;
OuvreLog* A::ol = new OuvreLog(); |
Et ca fonctionne... à moitié !
En effet, dans ce cas le destructeur de OuvreLog n'est jamais appelé, et le fichier pas fermé.
Bon, je sais que de toute façon, un bon OS va fermer tous les handle de fichier encore ouverts lors de la terminaison d'un programme, mais j'aimerais bien quand même fermer proprement mon fichier moi-même (ne serait-ce que pour vérifier l'arrêt correct).
Quelqu'un aurait une idée ? Ou alors une façon complètement différente de procéder ?
Merci.