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

Qt Discussion :

Constructeur et Qt


Sujet :

Qt

  1. #1
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut Constructeur et Qt
    Bonjour,

    J'ai vraiment une question idiote, qui de plus me traumatise depuis le défi Qt.

    Avant, pour chaque classe qui hérite de Qt, si j'avais besoin d'un bouton dans ma classe, je définissais un pointeur sur un QButton dans la classe, que j'allais contruire ( new QButton ) dans le constructeur ( et détruire proprement dans le destructeur ).
    Le problème, c'est que dans le C++ on dit qu'il faut évité d'utiliser les pointeurs.
    Deuxième point, c'est que dans certains ( Inclusion d'un element dans un QGridLayout ( ou autre ) ), les éléments sont détruit par Qt automatiquement.

    Maintenant, je veux faire en sorte de ne pas utiliser de pointeur \o/.

    Mais pour le code suivant:

    class.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Bar : public QWidget
    {
         private:
              QButton button;
         public:
              Bar(void);
    };
    class.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Bar :: Bar(void)
    {
         button = QButton(this);
    }
    Une chose me turlupine. Il va me construire deux fois le QButton n'est ce pas ( constructeur vide, puis constructeur avec this comme paramètre )?
    Si on construit deux fois le QButton, je trouve cela un peut inutile. Ou alors, j'ai vraiment perdu une notion du C++.

    Pourriez vous avoir l'obligeance de m'éclaircir les idées, et me dire quel est la bonne pratique à utiliser ?

    Merci beaucoup
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  2. #2
    Membre éprouvé
    Avatar de ymoreau
    Homme Profil pro
    Ingénieur étude et développement
    Inscrit en
    Septembre 2005
    Messages
    1 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur étude et développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 154
    Par défaut
    Moi je crée mes objets en composition sans pointeur dans la mesure du possible. Pour ce qui est de la création de 2 objets, ça dépend de l'implémentation de l'opérateur égal ! C'est donc propre à chaque classe, je sais que dans Qt il y a un système qui optimise ce genre de choses en utilisant de manière transparente des références partageant les mêmes données pour éviter les copies inutiles, mais je ne pourrais pas t'en dire plus sur le sujet.

    En tout cas, dans ton code, il y a une manière C++ et simple d'éviter la copie : utiliser la "vraie" initialisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Bar :: Bar(void) : button(this)
    {
    }
    Cela donnera directement l'argument au moment de la création de ton bouton, alors que le code placé dans le constructeur est exécuté juste après sa création.

  3. #3
    Inactif  


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

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    je sais que dans Qt il y a un système qui optimise ce genre de choses en utilisant de manière transparente des références partageant les mêmes données pour éviter les copies inutiles, mais je ne pourrais pas t'en dire plus sur le sujet.
    Il s'agit du système COW (copy on write) qui permet de ne pas copier toute les données lors de la duplication d'un objet mais uniquement lors de la première modification de ces données : http://qt.developpez.com/doc/latest/implicit-sharing/

    la "vraie" initialisation
    Ca s'appelle un liste d'initialisation
    A lire : http://cpp.developpez.com/faq/cpp/?p...EUR_liste_init

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut
    Vous avez raison, la liste d'initialisation est la meilleure methode, mais je ne suis pas completement sur que cela fonctionne tout le temps (par exemple, des parametres calculer selon les autres variables, ou je ne sais quoi).
    Et puis, cela va me faire de longue liste d'initialisation

    Pour la Copy On Write, je ne pense pas que ce soit ce qui correspond a ma question. Mais merci de m'apprendre toujours plus.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Inactif  


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

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Pour le COW, c'était pour préciser les propos de YoniBlond, pas répondre à la question

    Et puis, cela va me faire de longue liste d'initialisation
    pas très grave. Et vaux mieux ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Bar::Bar(void) :
        button1(this),
        button2(this),
        button3(this),
        button4(this),
        button5(this),
        button6(this),
        button7(this)
    {
    }
    que de payer le "coût" d'une copie...

    Imagine qu'a la place d'un simple bouton, tu as une très grosse classe (par exemple contenant plusieurs std::vector de taille 10000000) : les appels répétés à l'opérateur de copie peut être très couteux.

    PS: je viens de remarquer que QVector utilise le COW, au contraire de std::vector... une bonne raison d'utiliser QVector par défaut
    PS2 : pour un simple QPushButton, ce n'est pas très grave de faire une copie. QPushButton n'utilise pas le COW mais utilise QPixmapCache, ce qui évite de copier plusieurs fois le pixmap (http://qt-quarterly.developpez.com/qq-12/qpixmapcache/)

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut.
    J'ai lue rapidement...
    Mais
    1- les QObject ne sont pas et ne doivent pas être copiable!!! C'est pas prévue pour. C'est pour cela que l'operateur = est private.
    2- les widget sont reparenté automatique => forte probabilité de problème mémoire si on utilise pas des pointeurs.

    http://qt.developpez.com/faq/?page=g...ire#memoire-qt
    http://qt.developpez.com/faq/index.p...qobject-membre

    Sans le cas de Qt, les widget oblige l'utilisation de pointeur. Mais en contre partie, la mémoire au automatiquement géré (GC interne).
    Il y as quelques pointeur intelligent intéressant comme QPointer ou QWeakPointer qui peuvent être utile.

  7. #7
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut
    Merci pour le complément d'information Yan, mais je reste toujours un peu perdu.

    En plus, ce que je ne comprends pas vraiment ( car j'ai l'habitude de jouer avec les pointeurs ), c'est que même si je le détruit à la main, je n'aurais pas de problème ( pas de double free ... )
    Quelle magie fait que ce code fonctionne ? Lorsqu'un widget est ajouté au layout, le layout le reparente automatiquement avec son widget propriétaire (dialog dans ce cas-ci). Finalement, lorsque la fonction se termine, le destructeur de dialog supprime tous les objets et nettoie la mémoire.
    Oui c'est magique certes, mais pour quelqu'un comme moi qui vient du monde du C, et qui aime bien faire sa gestion des pointeurs à la main, j'ai un peu de mal.
    Car si je fais tous mes pointeurs, et que je laisse Qt les détruire, pour moi, il y aura comme un problème dans mon code ....

    Les autres : Au choix. Il peut être intéressant de ne pas utiliser de pointeur pour éviter de faire les allocation à la main. Ceci ne pose aucun problème avec le système de destruction parent/enfant, car ils seront détruit avant la classe. Toute fois il ne faut pas oublier de mettre this en parent.
    Certes, mais cela veut dire que le destructeur de l'objet de Qt est complètement vide ou inutile.
    Je dis ça, car si je fais un QGridLayout, que je met pour parent ma classe qui hérite de QWidget, ce QGridLayout est alloué statiquement ( membre qui n'est pas un pointeur ). Je lui donne this à la construction car je veux l'attacher à ma classe ( ce qui est normal ), dans le destructeur de ma classe, le destructeur du QGridLayout va être appelé ... mais il va aussi être appelé par le constructeur de ma classe ( enfin, de QWidget ). Donc, il me semblerait que j'aurais une double désallocation de mon QGridLayout ( pourtant je suis sur que cela va marcher ).

    Donc, maintenant, je vais voir ce que font les gars de Qt dans les exemples, mais je me demande toujours qu'elle est la meilleure organistation du code, dans un cas ou l'on hérite de QWidget, que l'on va faire un QGridLayout, deux QGroupBox, et quatres QButtons ( deux dans chaque QGroupBox ). Car c'est facile de se perdre ( même si cet exemple est un petit exemple ) et encore plus si on ne sais pas quoi faire avec la mémoire.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut
    Finalement, dans l'exemple de Qt ( Basic drawing ( OpenGL ) ), ils n'utilisent que des pointeurs, et ne prennent même pas le soin de faire un destructuer O_o.

    Du coup je vais faire pareille, et croire dans le super design de Qt.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  9. #9
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    En plus, ce que je ne comprends pas vraiment ( car j'ai l'habitude de jouer avec les pointeurs ), c'est que même si je le détruit à la main, je n'aurais pas de problème ( pas de double free ... )
    Pas toujours; Tous dépend ce que tu détruit et de l'ordre de destruction
    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    QWidget *w = new QWidget;
    QWidget *w2 = new QWidget;
    QVBoxLayout * layout = new QVBoxLayout(w);
    layout ->addwidget(w2);
    que se passe t'il si tu fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete W2;
    delete w1;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete W1;
    delete w2;
    y en as un qui fait une erreur mémoire et pas l'autre.

    Autre exemple
    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
    class widg :public QWidget
    {
        QWidget w2;
        QWidget w;
     
     
    public :
        widg (...)
        {
             QVBoxLayout * l = new QVBoxLayout(this);
             l->addWidget(&w);
             QVBoxLayout * layout = new QVBoxLayout(&w);
             layout->addWidget(&w2);
        }
    };
    erreur mémoire ou pas erreur mémoire?

    En faite, je comprend pas trop ce que tu n'as pas compris.

  10. #10
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Finalement, dans l'exemple de Qt ( Basic drawing ( OpenGL ) ), ils n'utilisent que des pointeurs, et ne prennent même pas le soin de faire un destructuer O_o.

    Du coup je vais faire pareille, et croire dans le super design de Qt.
    QObject implémente un Garbadge collector.
    Quand un QOBject parent est détruit, il détruit ses enfants.

  11. #11
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut
    Ce n'est pas vraiment que je n'ai pas compris ( maintenant c'est bon, je veux dire ). C'est juste que je préfère faire une gestion totale de ma mémoire, au lieu d'avoir une gestion non controllée, que je risque de faire des erreurs.

    Par contre, règle que j'ai toujours suivi:
    " On détruit les objets dans l'ordre inverse de la construction "

    Dans le deuxième exemple, je penserai plus à erreur de mémoire ( du moins, il y a trop de risque pour continuer à utiliser ce genre de code ).

    QObject implémente un Garbadge collector.
    Quand un QOBject parent est détruit, il détruit ses enfants.
    Que cela soit appelé Garbage Collector, je suis contre.
    Car le genre que je fais une allocation à la main, qui n'est pas attaché à Qt ... et bah, j'ai une fuite si je ne détruit par à la main. Donc du coup, j'oserai dire que ce n'est pas un vrai garbage collector.
    Sinon, le "garbage collector" est il aussi actif lorsque l'on ne donne pas d'objet parent?
    ( new QButton(0) // par exemple )
    Dernière chose, qu'un QObject détruise ses enfants, cela ne me choque pas trop, faut juste que j'en prenne plus conscience dans mon code.
    ( Cela serait comme un std::vector qui détruirait les pointeurs qu'il a dans la liste )
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  12. #12
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Ce n'est pas vraiment que je n'ai pas compris ( maintenant c'est bon, je veux dire ). C'est juste que je préfère faire une gestion totale de ma mémoire, au lieu d'avoir une gestion non controllée, que je risque de faire des erreurs.
    En c++ on va detester le delete et déléguer cela à des smart pointeur ou à Qt pour le cas des QObject.


    Dans le deuxième exemple, je penserai plus à erreur de mémoire ( du moins, il y a trop de risque pour continuer à utiliser ce genre de code ).
    c'est bien une erreur car w est détruit avant w2. Quand w est détruit, il détruit w2. Pui sla classe détruit encore une fois w2
    et comme tu la dit
    " On détruit les objets dans l'ordre inverse de la construction "

    Que cela soit appelé Garbage Collector, je suis contre.
    Car le genre que je fais une allocation à la main, qui n'est pas attaché à Qt ... et bah, j'ai une fuite si je ne détruit par à la main. Donc du coup, j'oserai dire que ce n'est pas un vrai garbage collector.
    Ben si s'en est un mais que pour le QOBject. IL ne pourra pas gérer le reste. Après c'est smart_ptr

    Sinon, le "garbage collector" est il aussi actif lorsque l'on ne donne pas d'objet parent?
    ( new QButton(0) // par exemple )
    non, la c'est a toi de le détruire. Tu devrais relit les deux liens de la faq.

    Dernière chose, qu'un QObject détruise ses enfants, cela ne me choque pas trop, faut juste que j'en prenne plus conscience dans mon code.
    ( Cela serait comme un std::vector qui détruirait les pointeurs qu'il a dans la liste )
    exactement.
    Un truc qu'il faut bien comprendre. Si on détruit un QObject et qu'il est parenté, il se sépare de son parent et ne pose pas de problème. Mais il va détruire ses enfants.

    Au lieu de faire un delete, il est souvent préférable d'utiliser deleteLater() sur un QOBject. Ça met un évènement dans l'eventloop qui va le détruire . Car si tu fait un delete pendant un signal, ca peut foutre la merde.

  13. #13
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 122
    Billets dans le blog
    148
    Par défaut
    Merci beaucoup,

    Je pense que maintenant, la gestion de la memoire avec Qt ira un peu mieux dans mes programmes.

    (Y a plus qu'a voir comment bien structurer les objets lorsque l'on veut faire une belle interface).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

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

Discussions similaires

  1. [Reflection] Récupérer un constructeur ayant un paramètre int
    Par narmataru dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 09/07/2004, 09h53
  2. [VB6]Déclaration d'un Constructeur Spécialisé
    Par TagadaTsoin dans le forum VB 6 et antérieur
    Réponses: 21
    Dernier message: 26/05/2004, 14h09
  3. [Constructeur]Pb avec la surcharge d un constructeur
    Par cmoulin dans le forum Langage
    Réponses: 3
    Dernier message: 26/04/2004, 09h29
  4. Capture d'exception dans un constructeur
    Par declencher dans le forum Composants VCL
    Réponses: 8
    Dernier message: 03/02/2004, 12h52
  5. pb constructeurs classes dérivant classe abstraite
    Par Cornell dans le forum Langage
    Réponses: 2
    Dernier message: 10/02/2003, 19h02

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