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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
// fichier a.cpp
#include "a.hpp"
ofstream A::ferr;
L'idée, c'est que je puisse de partout faire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
   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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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.