Question
Je suis très confus quant à l'utilisation de destructeurs dans Qt4 et j'espère que vous pourrez m'aider.
Quand j'ai une méthode comme celle-ci (avec "Des" est une classe):
void Widget::create() {
Des *test = new Des;
test->show();
}
comment puis-je m'assurer que ce widget sera supprimé après sa fermeture?
Et en classe " Des " j'ai ceci:
Des::Des()
{
QPushButton *push = new QPushButton("neu");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(push);
setLayout(layout);
}
Où et comment dois-je supprimer * push et * layout? ce qui devrait être dans le destructeur Des :: ~ Des ()?
La solution
Une autre option pour utiliser deleteLater ()
, ou les parents, consiste à utiliser la fonctionnalité de suppression à la fermeture pour les widgets. Dans ce cas, Qt supprimera le widget à la fin de son affichage.
Des *test = new Des;
test->setAttribute( Qt::WA_DeleteOnClose );
test->show();
J'aime l'utiliser avec l'arborescence d'objets conservée par Qt afin de définir la suppression lors de la fermeture de la fenêtre. De plus, tous les widgets de la fenêtre ont un parent spécifique, de sorte qu'ils soient également supprimés.
Autres conseils
Qt utilise ce qu'ils appellent les arborescences d’objets et est un peu différent de l’approche RAII typique.
La classe QObject
constructeur prend un pointeur sur un parent QObject
. Lorsque ce QObject
parent est détruit, ses enfants seront également détruits. Ceci est un modèle assez répandu dans les classes de Qt et vous remarquerez que beaucoup de constructeurs acceptent un paramètre * parent
.
Si vous consultez certains des Qt exemples de programmes , constatent qu'ils construisent réellement la plupart des objets Qt sur le tas et tirent parti de cet arbre d'objets pour gérer la destruction. Personnellement, j’ai trouvé cette stratégie utile, car les objets graphiques peuvent avoir une durée de vie particulière.
Qt ne fournit aucune garantie supplémentaire au-delà du C ++ standard si vous n'utilisez pas QObject
ou une sous-classe de QObject
(tel que QWidget
).
Dans votre exemple particulier, rien ne garantit que quelque chose soit supprimé.
Vous voudrez quelque chose comme ceci pour Des
(en supposant que Des
est une sous-classe de QWidget
):
class Des : public QWidget
{
Q_OBJECT
public:
Des(QWidget* parent)
: QWidget(parent)
{
QPushButton* push = new QPushButton("neu");
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(push); // this re-parents push so layout
// is the parent of push
setLayout(layout);
}
~Des()
{
// empty, since when Des is destroyed, all its children (in Qt terms)
// will be destroyed as well
}
}
Et vous utiliseriez la classe Des
comme suit:
int someFunction()
{
// on the heap
Des* test = new Des(parent); // where parent is a QWidget*
test->show();
...
// test will be destroyed when its parent is destroyed
// or on the stack
Des foo(0);
foo.show();
...
// foo will fall out of scope and get deleted
}
La réponse de Richardwb est bonne - mais l’autre approche consiste à utiliser la fente deleteLater, comme suit:
Des *test = new Des;
test->show();
connect(test, SIGNAL(closed()), test, SLOT(deleteLater()));
Évidemment, le signal closed () peut être remplacé par le signal de votre choix.
Ce tutoriel suggère que vous n'avez pas besoin de supprimer explicitement les widgets ajoutés aux widgets parents. Il dit aussi que ça ne fait pas mal de les supprimer non plus.
(Je n'ai pas testé cela, mais je suppose que tant que vous les supprimez explicitement avant que le widget parent ne soit supprimé, cela devrait être OK.)
Dans la plupart des cas, vous devez créer des widgets sur la pile:
QPushButton push("neu");
De cette façon, ils sont supprimés quand ils deviennent hors de portée. Si vous voulez vraiment les créer sur le tas, il est de votre responsabilité d'appeler delete lorsqu'ils ne sont plus nécessaires.