Partage
  • Partager sur Facebook
  • Partager sur Twitter

Implémentation de classe avec un file comme membre

Sujet résolu
    20 octobre 2019 à 6:44:37

    Bonjour,

    Je veux créer une classe et je ne sais pas si je m'y prends bien. Dans le .h que je dois respecter j'ai:

    class Exemple {
    private:
    	
    	std::queue<ObjetDuneClasse> Elements;
    
    public:
        	Exemple ();
        	~Exemple ();
    	
    };

    Dans le .cpp, j'ai un doute que mon constructeur & destructeur sont bons:

    // Constructeur
    Exemple::Exemple() {
    	std::queue<ObjetDuneClasse> Elements;
    }
    
    // Destructeur
    Exemple::~Exemple() {
    	while (!Elements.empty())
    	{
    		Elements.pop();
    	}
    }

    Ai-je le bon constructeur et destructeur qui respectent le header?

    • Partager sur Facebook
    • Partager sur Twitter
      20 octobre 2019 à 8:22:06

      Tu n'as pas besoin de vider manuellement la queue, c'est automatique. Donc pas besoin de destructeur explicitement déclaré.

      Et ce que tu fais dans ton constructeur, c'est déclarer une nouvelle variable locale, qui masque ta variable membre. Active les warnings de ton compilateur, c'est le genre d'erreur qu'il peut détecter.

      prog.cc:15:33: warning: declaration shadows a field of 
      'Exemple' [-Wshadow]
      prog.cc:5:33: note: previous declaration is here
          std::queue<ObjetDuneClasse> Elements;
                                      ^



      -
      Edité par gbdivers 20 octobre 2019 à 8:24:47

      • Partager sur Facebook
      • Partager sur Twitter
        20 octobre 2019 à 14:07:45

        Salut,

        Avec cette classe, tu n'as absolument rien à faire au niveau du constructeur (1) et du destructeur (2):

        1- le simple fait de déclarer le membre Elements comme étant une std::queue<ObjetDuneClasse> suffit à faire en sorte que chaque instance de ta classe dispose d'une file contenant des ObjetDuneClasse

        2- Les règles du C++ sont claires : le destructeur d'une classe est systématiquement appelé lorsque l'on quitte la portée dans laquelle une variable est déclarée.

        Quand plusieurs variables sont déclarées dans la même portée, leur destruction s'effectue dans l'ordre inverse de leur déclaration

          En voici un petit exemple commenté pour bien comprendre:

        int main(){
            Exemple ex1; // on crée une variable de type Exemple
            Exemple ex2; // nommée ex1 et une autre nommée ex2
            /* du code, sans importance */
            if(une_condition_quelquonque){
                Exemple ex3; // on crée une autre variable nommée ex3
                /* on peut utiliser ex1, ex2 et ex3 ici */
                
            } // ex3 est détruite ici, et son destructeur est automatiquement appelé
            /* on peut utiliser ex1 et ex2, qui existent toujours, 
             * mais pas ex3 qui n'existe déjà plus 
             * ( comprend: la variable a été détruite, et le
             * compilateur ne sait même plus qu'elle a existé )
             */
        
        }  // ex2 sera détruit en premier, 
           // et son destructeur sera appelé automatiquement
           // ensuite, ce sera le tour de ex1

        Les classes (comme les différentes collections) de la bibliothèque standard sont toutes développées de telle manière à ce qu'elle libère automatiquement les ressources qu'elles utilisent lorsque leur destructeur est appelé :

        • les flux et les fichiers sont correctement fermés
        • les collections sont correctement vidées, leur contenu correctement détruit (du moins, s'il n'y a pas eu recours à l'allocation dynamique de la mémoire pour créer le contenu)
        • les mutexes et autres joyeusetés du genre sont correctement levés
        • j'en passe, et sans doute de meilleures

        Ce sont exactement les mêmes règles qui s'appliquent aux différents membres de ta classe:

        lorsque tu crées une instance de ta classe, les membres seront créés dans l'ordre exacte de leur déclaration

        lorsque l'instance de ta classe est détruite (entre autres, parce que tu sors de la portée dans laquelle l'instance a été déclarée), les membres de la classe sont automatiquement détruits (et leur destructeur respectif appelé) dans l'ordre inverse de leur déclaration.

        La grosse difficulté à laquelle tu pourrais être confronté viendra de la manière dont les éléments de ta liste seront gérés.  Trois possibilités s'offrent alors à toi:

        1. Les éléments sont créés sans avoir recours à l'allocation dynamique : (le membre de ta classe est de type std::queue<UneClasse> :aucun problème, la pile sera correctement vidée et son contenu sera correctement détruit
        2. les éléments sont créés en ayant recours à l'allocation dynamique de la mémoire, mais tu utilise les pointeurs intelligent (std::unique_ptr / std::shared_ptr) dans la file.  Le membre de ta classe est donc de type std::queue<std::unique_ptr<UneClasse>> (par exemple) : aucun problème, les pointeurs intelligents s'assurent de libérer la mémoire qui leur a été allouée lors de leur destruction
        3. les éléments sont créés en ayant recours à l'allocation dynamique "à l'ancienne", le membre de ta classe est donc de type std::queue<Uneclasse *> : tu auras un problème, car il faudra t'assurer d'appeler delete sur chacun des éléments contenu dans ta file (un code moderne ne devrait jamais te mettre dans cette situation ;) )
        • Partager sur Facebook
        • Partager sur Twitter
        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
          20 octobre 2019 à 15:33:32

          Merci beaucoup gbdivers et koala01 

          J'ai bien compris grâce à vous!

          • Partager sur Facebook
          • Partager sur Twitter

          Implémentation de classe avec un file comme membre

          × 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