Partage
  • Partager sur Facebook
  • Partager sur Twitter

Utiliser un objet depuis divers autres objets

L'héritage des classes pourra m'aider ?

Sujet résolu
    16 avril 2008 à 19:59:32

    Bonjours à tous !

    Étant plus ou moins débutant en C++, et donc dans la POO, j'ai sûrement une lacune qui me bloque dans mon développement. :-°
    Donc dans mon projet, je suis entrain d'implémenter un objet pour générer des logs.
    Donc j'ai fais une classe de gestion de fichier texte ( qui fonctionne très bien ). ^^

    Mon problème est le suivant : Comme j'instancie plusieurs instance de mon fichier texte, il arrive que mes objets qui désire écrire des logs viennent à écrire ensemble dans le fichier .. et donc .. tout plante. :(

    Donc je me suis dis... Seule moyen, avoir 1 seule objet pour TOUT le projet et donc, il faut que chacun de mes objets qui vont vouloir écrire leurs logs, puissent accéder à cette objet de logs initialisé dans le main().

    Donc je me demande comment je peux faire un objet que j'initialiserai dans le main() et qui contiendrai une méthode AddLog() et qui serai appellable depuis n'importe quel objet ?
    P.S: J'utilise des threads dans mon programme... :D
    • Partager sur Facebook
    • Partager sur Twitter
      16 avril 2008 à 20:23:33

      Synchronise (par mutex) l'accès à ta fonction interne d'écriture dans le fichier de logs.
      • Partager sur Facebook
      • Partager sur Twitter
      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
        16 avril 2008 à 20:28:28

        Merci pour ta réponse.

        Ok je veux bien, mais si j'instancie plusieurs objets TextFile, le mutex fonctionnera quand même entre chaques instances ??
        • Partager sur Facebook
        • Partager sur Twitter
          16 avril 2008 à 20:31:04

          Il faut que toutes les instances de ta classe d'interface pointent vers un même objet interne commun que tu lieras à ton fichier.
          • Partager sur Facebook
          • Partager sur Twitter
          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
            16 avril 2008 à 21:51:36

            Ce genre de cas est en C, un des motifs d'utilisation de variable globale. En C++ on préfèrera un recourir à une classe singleton, c'est à dire une classe dont il n'existera qu'une seule instance dans l'unité de programme. Il existe plusieurs façons de faire un singleton, en fonction, des conditions, des raffinements souhaités, et de l'age du capitaine (paramètre capital quand on aime le beau code ^^ ).

            Un exemple de singleton très simple,

            class Log
            {
            private:
                Log(const std::string & filename = "log.log"){/* ouverture du fichier de log */}  
            public:
                ~Log(){/* flush et fermeture du fichier de log */}
                friend Log & GetLog();
                void WriteLog(const std::string & data);
            }
            
            inline Log & GetLog(){static Log s_Log;return s_Log;}
            

            Tu remarqueras que le constructeur est privé, ce qui interdit la création d'une instance de la classe de Log, en dehors de la fonction amie GetLog. L'avantage de cette méthode, sera de créer le log automatiquement, dés que le programme en aura besoin.

            C'est vraiment du singleton basique, mais ça marche.

            GetLog().WriteLog("Ma ligne de log");
            


            Basiquement, avec ça tu devrais pouvoir faire une classe log, qui te donneras pleinement satisfaction sur un programme monothread. En multithreading, il faudra synchroniser tout ça, notamment en réalisant toutes les écritures dans le log en section critique. Je ne saurais pas te dire quelle est la meilleure tactique, en fait la réponse dépend de ce que tu veux faire et des contraintes que tu dois respecter.
            • Partager sur Facebook
            • Partager sur Twitter
            Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
              17 avril 2008 à 18:22:14

              Citation : int21h

              En multithreading, il faudra synchroniser tout ça, notamment en réalisant toutes les écritures dans le log en section critique. Je ne saurais pas te dire quelle est la meilleure tactique, en fait la réponse dépend de ce que tu veux faire et des contraintes que tu dois respecter.



              Ben ce que je veux faire, c'est que mes n threads écrivent dans un fichier de log ce qu'ils font ( si je le demande au démarrage du projet )...
              Y a pas trop de trucs à respecter ... simplement faire des logs ...

              Mais merci ! Je vais me renseigner à partir de tes explications !!! :)

              Edit : Bon je vient d'essaier de faire la classe.. mais j'ai pas vraiment réussi... :o
              J'ai donc fais une classe Log en singleton sans soucis.
              Je l'importe dans le fichier du int main(), puis j'instancie et j'écris une ligne de log... ca va !

              Mais, maintenant mes questions :

              Pour commencer, j'ai donc écrit toute ma classe dans un seule fichier.
              Mais ce fichier je l'ai appelé log.cpp...
              Du coup j'ai un #include "log.cpp"... C'est bon ca ?? o_O


              Dans ma classe, je doit initialiser ma variable singleton qui contiendra le pointeur vers mon objet avec la ligne Log *Log::singleton = NULL;
              Normalement elle est placé à la fin de la classe...
              Mais si je fais ca, et que fais mon include de mon fichier, il met toujours :
              main.o:(.bss+0x0): multiple definition of `Log::singleton'
              log.o:(.bss+0x0): first defined here

              Parcontre si je met la ligne Log *Log::singleton = NULL; dans le fichier main.cpp ca compile et fonctionne...


              Maintenant, comment je fais pour passer mon objet Log à mes objets pour qu'ils puissent créer leur logs ?


              Voici ma classe Log :
              #include "textfile.hpp"
              #include <iostream>
              
              //~ !! Singleton Class !!
              class Log
              {
              	private:
              		Log( const std::string & LogFilePath = "./logfile.log" )
              		{
              			std::cout << "Initializing log file..." << std::endl;
              			
              			//~ Initiaize text file
              			TextFileForLogs = LogFilePath;
              			
              			std::cout << "Log file Initialized." << std::endl;
              		}
              		
              		~Log()
              		{
              			std::cout << "Closing log file..." << std::endl;
              			
              			TextFileForLogs.CloseFile();
              			
              			std::cout << "Log file closed!" << std::endl;
              		}
              	
              	public:
              		//~ Function to write a line in the text file
              		void WriteLog( const std::string LogMessageToAdd )
              		{
              			
              			//~ Wait for the Text File to be Free
              			while ( 1 )
              			{
              				
              				if ( TextFileForLogs.IsFree() )
              				{
              					//~ File is free, write the log
              					TextFileForLogs.OpenForOutput( false );
              					TextFileForLogs.WriteLine( LogMessageToAdd );
              					TextFileForLogs.CloseFile();
              					
              					break;
              				}
              			}
              			
              		}
              		
              		//~ Function to create the Singleton Class
              		static Log *GetInstance ()
              		{
              			if (NULL == singleton)
              			{
              				
              				std::cout << "creating singleton." << std::endl;
              				singleton =  new Log;
              				
              			} else {
              				
              				std::cout << "singleton already created!" << std::endl;
              				
              			}
              			
              			return singleton;
              		}
              		
              		//~ Function to distroy Singleton Class
              		static void kill ()
              		{
              			if (NULL != singleton)
              			{
              				delete singleton;
              				singleton = NULL;
              			}
              		}
              
              	
              	private:
              		static Log 		*singleton;
              		TextFile		TextFileForLogs;
              };
              


              Et pour l'initialiser, je fais donc :
              Log		*LogFile;		//~ Initialize the Log Object ( SingleTon Class )
              LogFile		= Log::GetInstance();
              
              • Partager sur Facebook
              • Partager sur Twitter
                17 avril 2008 à 21:38:22

                1) transforme tes tab en 4 espaces pour l'affichage

                2) on ne fait pas de while(1) sans sleep et encore j'irais pour :
                while( !TextFileForLogs.IsFree() )
                    Sleep( 100 );
                
                //...
                


                3) Tu peux aussi utiliser un compteur d'accès que tu incrementera à chaque getInstance et que tu décrémentera à chaque Release ou Kill. Sinon tu permet de libérer le singleton même si d'autres thread en on encore besoin.

                4) Ton constructeur prend un paramètre mais il n'y a aucune chance qu'il en reçoive un.
                • Partager sur Facebook
                • Partager sur Twitter
                  17 avril 2008 à 22:34:44

                  Aucun intérêt de s'embêter à faire que instance() génère un Log si aucun n'a été construit jusqu'à présent.
                  C'est compliqué, cela limite ta bibliothèque à un seul composant dans ton appli, et en plus ta contrainte multi-threads fait que tu n'es pas autorisé à faire de la construction paresseuse/implicite.

                  http://www.siteduzero.com/forum-83-179 [...] ingleton.html


                  @MatteX, il y a des recettes de spin mutex qui ne font justement aucun sleep().
                  Dans mes souvenirs, c'est un truc efficace quand il y a très peu d'accès bloqués, ou alors qu'ils ne durent pas. C'est aussi le truc que j'ai tendance à utiliser en dernier recours pour préférer les mutex plus classiques à la place.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                    24 mai 2008 à 13:10:32

                    Bonjour à tous !

                    Ce matin je me suis relancer dans cette histoire et j'ai réussi !!
                    Enffet y avait un manque de compréhension de ma part sur l'utilisation du Singleton.
                    Là où je faisais l'erreur c'est qu'a chaque ligne que je voulais écrire, juste derrière je cherchais à supprimer mon objet log. :lol:

                    Bref, maintenant ca marche impec !
                    Je vais pouvoir sortir ma premier release !!! Ouf !! ^^


                    Merci à vous pour vos messages qui m'ont aider ! :)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Utiliser un objet depuis divers autres objets

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown