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

Discussion :

Petite incompréhension concernant les destructeurs

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Août 2010
    Messages : 126
    Points : 69
    Points
    69
    Par défaut Petite incompréhension concernant les destructeurs
    bonjour a tous je fais appelle a vous car j'ai besoin de votre aide concernant les destructeur. Sa peut vous paraitre ridicule comme probleme mais moi je n'y comprend rien, et ceux malgré avoir lu la faq C++ sur les destructeurs.

    Voici mon probleme : j'ai creer une classe et je l'appelle dans mon programme comme ci dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    void laPageAccueil::afficherPageEnregistrerLivre()
    {
        leLivre *unLivre = new leLivre(this);
        unLivre->exec();
        delete unLivre; // on appelle donc unLivre->~leLivre() 
    }
    et voici le destructeur que j'ai creer est qui est appelé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    leLivre::~leLivre()
    {
        delete enregistrerLivreLabel;
        delete livreGroupBox;
        delete horizontalLayoutWidget;
        delete horizontalLayout;
        delete isbnLabel;
        delete isbnLineEdit;
        delete horizontalLayoutWidget_2;
        delete horizontalLayout_2;
        delete titreLabel;
        delete titreLivreLineEdit;
        delete auteurGroupBox;
        delete horizontalLayoutWidget_4;
        delete horizontalLayout_4;
        delete auteurLabel;
        delete auteurLineEdit;
        delete progressBar2;
        delete horizontalLayoutWidget_3;
        delete horizontalLayout_3;
        delete validerButton2;
        delete fermerButton2;
        delete consigneLabel2;
    }
    et je ne comprend pas pourquoi cela plante.
    Dans la leçon C++ il est dit qu'a chaque "new" il est indispensable de les supprimer par la suite avec un delete afin que les objets creer ne trainent pas en mémoire.
    En effet si on prend la premiere ligne du destructeur : delete enregistrerLivreLabel;
    je fait un delete, mais si je le fais c'est parce que dans le programme il y a eu un enregistrerLivreLabel = new label(); il est donc normal que je le supprime par la suite en faisant un delete.
    Mais le programme plante et j'ai vraiment du mal a comprendre pourquoi ,par contre quand j'enleve tout les deletes du destructeurs, le programme marche mais dans ce cas tous les objets creer resteront en mémoire et celle ci ne sera pas liberer.

    J'ai certainement faux dans ma logique, puisque je n'arrive pas a resoudre mon probleme, j'aimerai donc que vous m'expliquiez mon probleme.
    Je vous remercie d'avance pour les explications que vous m'apporterez

  2. #2
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 475
    Points
    11 475
    Billets dans le blog
    11
    Par défaut
    Es-tu sur de ne pas 'delete' d'éléments qui :
    - n'ont pas été créés (sans avoir été initialisés à NULL)
    - on déjà été détruits autre part (et n'ont pas été remis à NULL)
    - qui ne sont pas des pointeurs.

    Pose toi déjà ces 3 questions là, je pense qu'après ça ira beaucoup mieux.
    Sinon, ta logique est évidemment la bonne, à voir : un delete pour un new.
    Par contre une autre question que tu dois te poser est la légitimité de l'utilisation des pointeurs.
    Par exemple dans ta fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void laPageAccueil::afficherPageEnregistrerLivre()
    {
        leLivre *unLivre = new leLivre(this);
        unLivre->exec();
        delete unLivre; // on appelle donc unLivre->~leLivre() 
    }
    Il n'est pas nécessaire d'utiliser un pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void laPageAccueil::afficherPageEnregistrerLivre()
    {
        leLivre unLivre(this);
        unLivre.exec();
    }
    De manière générale, il est préférable de ne pas utiliser les pointeurs tant qu'on n'en a pas besoin.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Août 2010
    Messages : 126
    Points : 69
    Points
    69
    Par défaut
    et bien si je fais des delete c'est parce que le compilateur Qt m'a creer des objets du style QLabel *x = new QLabel();
    comme tu peux le voir ici sur ce morceau de code du constructeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     commandeLabel = new QLabel(commande);
            commandeLabel->setObjectName(QString::fromUtf8("commandeLabel"));
            commandeLabel->setGeometry(QRect(160, 50, 331, 16));
            QFont font;
            font.setFamily(QString::fromUtf8("MV Boli"));
            font.setPointSize(14);
            font.setBold(true);
            font.setWeight(75);
            commandeLabel->setFont(font);
            horizontalLayoutWidget_3 = new QWidget(commande);
            horizontalLayoutWidget_3->setObjectName(QString::fromUtf8("horizontalLayoutWidget_3"));
            horizontalLayoutWidget_3->setGeometry(QRect(470, 400, 160, 41));
            horizontalLayout_3 = new QHBoxLayout(horizontalLayoutWidget_3);
            horizontalLayout_3->setSpacing(6);
            horizontalLayout_3->setContentsMargins(11, 11, 11, 11);
            horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
            horizontalLayout_3->setContentsMargins(0, 0, 0, 0);
            validerButton3 = new QPushButton(horizontalLayoutWidget_3);
    mais le compilateur Qt n'a pas creer de destructeur c'est pour cela que j'en creer car je dois les supprimer, sinon le programme va prendre plus de place que prevu en mémoire. Voila pourquoi je dois creer un destructeur et voila aussi pourquoi j'ai fait mis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    leLivre *unLivre = new leLivre(this);
        unLivre->exec();
        delete unLivre; // on appelle donc unLivre->~leLivre()
    au lieu de ce que tu m'as dit. C'est pour supprimer les objet creer par Qt, a savoir (ce que j'ai mis au dessus, le constructeur)

  4. #4
    Membre averti
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Points : 346
    Points
    346
    Par défaut
    Citation Envoyé par momo-ben2A Voir le message
    et bien si je fais des delete c'est parce que le compilateur Qt m'a creer des objets du style QLabel *x = new QLabel(); [...] mais le compilateur Qt n'a pas creer de destructeur c'est pour cela que j'en creer car je dois les supprimer, sinon le programme va prendre plus de place que prevu en mémoire
    C'est normal quand on utilise Qt car la classe QObject se charge de faire le ménage dans son destructeur :

    QObjects organize themselves in object trees. When you create a QObject with another object as parent, the object will automatically add itself to the parent's children() list. The parent takes ownership of the object; i.e., it will automatically delete its children in its destructor. You can look for an object by name and optionally type using findChild() or findChildren().

    in http://qt.developpez.com/doc/latest/qobject.html

  5. #5
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 475
    Points
    11 475
    Billets dans le blog
    11
    Par défaut
    oui effectivement, Qt se charge déjà de détruire les objets que tu lui passes.
    En tout cas, le code que j'ai mis pass aussi par le destructeur de ta classe : le destructeur n'est pas appelé uniquement via 'delete' si l'objet a été alloué dynamiquement mais aussi lorsque l'on perd la visibilité d'une variable allouée statiquement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if (coincoin)
    {
       Glop * pGlop = new Glop();
       Glop glop;
    }
    // En sortant du if, on perd la visibilité de la variable 'glop' qui est donc détruite (et le destructeur de la classe Glop est appelé)
    // Par contre, on a perdu la visibilité de la variable 'pGlop', mais comme celle-ci a été allouée dynamiquement, la mémoire allouée est perdue (et le destructeur n'est évidemment pas appelé)

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Août 2010
    Messages : 126
    Points : 69
    Points
    69
    Par défaut
    donc si j'ai bien compris avec Qt il est inutile de creer des destructeurs car Qt fait automatiquement des delete lorsqu'on utilise des new.
    Et que donc ce que j'ai fait dans le programme c'est que j'ai tenter de supprimer des objets en mémoire qui on deja etaient supprimé juste avant par Qt.
    En faite avec Qt on ne se soucie pas de faire des delete lorsqu'on utilise des new car il les supprime tout seul. C'est bien sa ?

  7. #7
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Petite précision : en fait, ce qui se passe dans Qt, c'est que lorsque tu détruis un objet, ses enfants sont détruits aussi (et pas tous les objets Qt, ça serait trop facile ce n'est pas un garbage collector). Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    QObject o1 = new QObject();
    delete o1; // nécessaire sinon o1 pas détruit
     
    QObject o1 = new QObject();
    QObject o2 = new QObject(o1);
    delete o2; // o2 détruit mais pas o1
     
    QObject o1 = new QObject();
    QObject o2 = new QObject(o1);
    delete o1; // o1 et o2 détruit
    En fait, ton code simplement parce que tu détruis un objet qui est parent d'autres objets (et donc les détruits) puis tu essaies de détruire ces objets enfants (qui sont déjà détruit) -> erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    delete enregistrerLivreLabel; // ok
    delete livreGroupBox; // ok
    delete horizontalLayoutWidget; // ok
    delete horizontalLayout; // erreur ensuite -> la ligne au dessus supprime tous les enfants
    ...
    Le plus simple avec Qt est d'appeler le delete uniquement sur des objets sans parent... et de donner un parent à tout le monde ! Ou de créer les objets dans la pile. Donc jamais appeler de delete

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Août 2010
    Messages : 126
    Points : 69
    Points
    69
    Par défaut
    oki donc si sa bug c'est parce que j'ai voulu supprimer 2 fois le meme objet, et pour eviter sa , au lieu de me casser la tete a detruire chaque objet, je detruit simplement l'objet qui n'a pas de parent et Qt en fonction de cela detruit automatiquement les objets qui ont le parent. C'est bien sa ?

    2eme question, j'ai pas tres bien compris quand tu me dis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    delete enregistrerLivreLabel; // ok
    delete livreGroupBox; // ok
    delete horizontalLayoutWidget; // ok
    delete horizontalLayout; // erreur ensuite -> la ligne au dessus supprime tous les enfants
    c'est ce : erreur ensuite -> la ligne au dessus supprime tous les enfants

    a quoi tu vois que la ligne au dessus supprime tous les enfants ? et donc a quoi tu vois que c'est un parent ?

Discussions similaires

  1. Réponses: 1
    Dernier message: 06/01/2011, 16h29
  2. Petite incompréhension sur les relations
    Par slacky dans le forum Microsoft Dynamics CRM
    Réponses: 1
    Dernier message: 09/08/2010, 22h26
  3. Réponses: 2
    Dernier message: 07/05/2007, 16h46
  4. Petite erreur concernant les parenthèses
    Par bugland dans le forum Langage
    Réponses: 14
    Dernier message: 04/01/2007, 10h21
  5. Réponses: 11
    Dernier message: 21/06/2005, 10h16

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