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

SL & STL C++ Discussion :

Objets dérivé de std::ostream et manipulateur


Sujet :

SL & STL C++

  1. #1
    Sub
    Sub est déconnecté
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2003
    Messages : 20
    Points : 19
    Points
    19
    Par défaut Objets dérivé de std::ostream et manipulateur
    Bonjour à tous.

    Je suis programmeur amateur et j'ai voulu me créer un logger pour mes programmes. Je voulais pouvoir l'utiliser de la même façon que std::cout, lui passer du texte et des manipulateurs comme std::endl;

    Mon problème c'est que dès mes premiers tests je me suis heurté à un petit problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
     
    class CLog : public std::ostream
    {
    };
    int main(void)
    {
        CLog Log;
        Log.rdbuf(std::cout.rdbuf());
        Log << "Test" << std::endl;
     
        return EXIT_SUCCESS
    }
    Cela compile et voilà ce que j'obtiens à l'exécution :
    Test
    abnormal program termination
    Le problème vient du std::endl puisque je n'ai plus le message d'erreur en l'enlevant. Par contre je n'ai aucune de la raison de cette erreur, qu'est-ce que j'ai foiré ?

    Merci d'avance.

  2. #2
    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 : 39
    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
    Et en restaurant le streambuf de Log avant de quitter le programme ? Parce que là potentiellement tu vas avoir deux flux qui vont détruire le même streambuf.

  3. #3
    Sub
    Sub est déconnecté
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2003
    Messages : 20
    Points : 19
    Points
    19
    Par défaut
    Bon je crois avoir trouvé la solution à ce problème. Je vous la donne, je pense que cela peut être intéressant.

    Bon tout d'abord je rappel que la programmation est un passe-temps pour moi, donc ne me lyncher pas si je dis des conneries .

    J'ai trouvé dans ce liens : http://www.tacc.utexas.edu/services/...g/cre_2288.htm
    qu'il fallait passer au constructeur un pointeur vers un streambuf.

    The scheme for deriving from the stream classes is slightly different in that you must always provide a pointer to a stream buffer. This is because the stream classes do not contain a stream buffer, as the file or string stream classes do.
    Donc voilà ce que j'aurais dû faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class CLog : public std::ostream
    {
        public :
            CLog(std::streambuf* stream) : std::ostream(stream) {}
    };
    Après une petite escapade du côté du code de la SL, voilà ce que j'ai pu découvrir :
    Le constructeur de ostream appel une fonction nommée init() (nom évocateur ?) de sa classe mère ios. Cette fonction prend en paramètre le fameux pointeur sur streambuf. Or rdbuf() n'appelle pas cette fonction elle.

    D'ailleur le code suivant compile et fonctionne sans afficher de 'abnormal program termination' :
    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 CLog : public std::ostream
    {
        public :
            void Initialisation(std::streambuf *stream) {init(stream);}
    };
     
    int main(void)
    {
        CLog Log;
        Log.Initialisation(std::cout.rdbuf());
        Log<< "test" << std::endl;
     
        return EXIT_SUCCESS;
    }
    Preuve qu'il est donc conseillé de fournir directement un pointeur sur stream au constructeur, à moins de vouloir se taper une fonction "Initialisation()" puisque init() est protégée.

    Cependant ceci compile et fonctionne également :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class CLog : public std::ostream
    {
        public :
            CLog(void) : std::ostream(0) {}
    };
    Apparemment l'important est que la fonction init() de la classe ios soit appelée même si on ne lui passe qu'un pointeur null. Le constructeur par défaut de ostream ne fait pas appel à cette fonction lui. Il est également protégé, ce qui empêche d'instancier un objet de type ostream.

    Donc la fontion init() fait des trucs louches avec les streambuf qui sont nécessaire puisque que std::endl fait mumuse avec eux également (il les flush automatiquement, comme ça, sans demander, le malotru), d'où l'engueulade par le programme à l'exécution. D'ailleurs un std::ends fonctionne très bien avec ma classe foireuse de mon premier message.

    Voilàààà, vous pouvez me balancer les pierres dessus pour les conneries que j'ai pu dire maintenant

    Laurent Gomila : Alors ta solution ne fonctionnait pas mais c'est également un problème dont il faut se soucier apparemment. Dans le cas où je partage le flux de std::cout, il faut juste que je m'assure que mon objet Log soit détruit avant std::cout, ce dernier étant global cela ne devrait pas être trop dur.

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

Discussions similaires

  1. Méthode POST avec std::ostream
    Par Guilbert69 dans le forum C++
    Réponses: 6
    Dernier message: 31/07/2008, 23h43
  2. Implémentation d'une classe dérivant de std::ostream
    Par three minute hero dans le forum SL & STL
    Réponses: 1
    Dernier message: 08/07/2008, 14h07
  3. Réponses: 3
    Dernier message: 19/12/2007, 21h45
  4. passer un objet dérivé a un objet parent
    Par airseb dans le forum C++
    Réponses: 9
    Dernier message: 30/10/2006, 19h11
  5. Réponses: 6
    Dernier message: 09/05/2006, 23h30

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