2009-09-17 20 views
11

Estoy muy confundido sobre el uso de destructores en Qt4 y espero que puedan ayudarme.
cuando tengo un método como este (con "Des" es una clase):destructores en Qt4

void Widget::create() { 
    Des *test = new Des; 
    test->show(); 
} 

cómo puedo estar seguro de que este control va a ser borrada después de que se cerró?

Y en la clase "Des" tengo esto:

Des::Des() 
{ 
    QPushButton *push = new QPushButton("neu"); 
    QHBoxLayout *layout = new QHBoxLayout; 
    layout->addWidget(push); 
    setLayout(layout); 
} 

dónde y cómo tengo que borrar * * empuje y diseño? ¿Qué debería estar en el destructor Des :: ~ Des()?

Respuesta

12

Otra opción para usar deleteLater(), o padres, es usar la funcionalidad de eliminar para cerrar para widgets. En este caso, Qt eliminará el widget cuando se termine de mostrarse.

Des *test = new Des; 
test->setAttribute(Qt::WA_DeleteOnClose); 
test->show(); 

me gustaría usarlo con el árbol de objetos que Qt mantiene, por lo que me puse eliminar al cerrar la ventana y todos los widgets en la ventana de tener un padre adecuado especifica, por lo que todos se borran también.

+0

esto parece funcionar muy bien. Gracias. Pero cuando creo 4 nuevos widgets "de prueba" por ejemplo y los vuelvo a cerrar, crear otro widget "de prueba" no costará más memoria, pero la aplicación aún usa tanto como memoria como cuando los 4 "widgets de prueba" todavía existiría. ¿Eso es normal? – Berschi

+1

@Berschi, es posible que Qt o su SO esté optimizando la memoria.Si el quinto widget que mencionas en tu comentario no causa que se use más memoria, no me preocuparía demasiado. Otra opción, si está preocupado, es encontrar una herramienta como valgrind y ejecutar su programa a través de ella. –

2

En la mayoría de los casos se debe crear widgets en la pila:

QPushButton push("neu"); 

De esta manera, se eliminan cuando se hacen fuera de alcance. Si realmente desea crearlos en el montón, entonces es su responsabilidad llamar a eliminarlos cuando ya no sean necesarios.

+1

Es un poco más complejo que eso. QT desencadenará la destrucción de algunos objetos en algunas situaciones (si están registradas con un elemento primario) y, por lo tanto, al asignarles la pila, se eliminaría la aplicación con una doble libre. –

+3

dribeas, creo que cuando se destruye un QObject, este se anula automáticamente del padre. – rpg

+1

Uso la asignación de pila con QObjects todo el tiempo y funciona bien. Gracias por el downmod desinformado. –

3

This tutorial sugiere que no necesite eliminar explícitamente los widgets que se han agregado a los widgets principales. También dice que no hace daño borrarlos tampoco.

(no he probado esto, pero supongo que todo el tiempo que los elimine de forma explícita antes de eliminar el widget padre, esto debe estar bien.)

+2

+1, pero al tratar de eliminarlos _después_ el widget principal se ha eliminado, termina con una eliminación doble y la aplicación está muriendo. –

21

Qt utiliza lo que ellos llaman object trees y es un poco diferente desde el enfoque típico de RAII.

La QObject clase constructor toma un puntero a uno de los padres QObject. Cuando ese padre QObject se destruye, sus hijos también serán destruidos. Este es un patrón muy común en las clases de Qt y notará que muchos constructores aceptan un parámetro *parent.

Si observa alguno de los Qt example programs, descubrirá que realmente construyen la mayoría de los objetos Qt en el montón y aprovechan este árbol de objetos para manejar la destrucción. Personalmente, también encontré esta estrategia útil, ya que los objetos de la GUI pueden tener vidas peculiares.

Qt no ofrece garantías adicionales más allá de C++ estándar si no está usando QObject o una subclase de QObject (como QWidget).


En su ejemplo particular, no hay garantía de que se elimine algo.

Usted querrá algo como esto por Des (suponiendo Des es una subclase 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 
    } 
} 

Y tendrá que utilizar la clase Des así:

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 
} 
+0

ok esto es muy útil, pero tengo una pregunta adicional: Cuando cierro este widget llamado "prueba", eso no significa que también se destruirá, ¿verdad? Tengo que destruirlo/eliminarlo por mí mismo. ¿Cómo debo hacer eso? – Berschi

+2

Si el widget no tiene una vida útil limpia y no hay padres con los que asociarlo, la mejor opción es usar la funcionalidad de eliminar al cerrar que cjhuitt menciona en otra respuesta. – richardwb

+0

solo para la aclaración, si hacemos que el "Pulsador" como miembro variable, entonces tenemos que eliminar el botón manualmente en el widget destructor o se borrará cuando el padre se elimine .. – Naruto

5

respuesta de Richardwb es uno bueno, pero el otro enfoque es usar la ranura deleteLater, así:

Des *test = new Des; 
test->show(); 
connect(test, SIGNAL(closed()), test, SLOT(deleteLater())); 

Obviamente, la señal closed() se puede reemplazar con la señal que desee.

+0

no hay SEÑAL (cerrado()) para este widget. Las SEÑALES son: customContextMenuRequested (QPoint), destroyed() y destruido (QObject *) – Berschi

+0

OK, bueno, era un concepto general, más que un ejemplo concreto. ¿Quizás puedas agregar una señal que se emita cuando tu objeto termine su trabajo? De todos modos, es un patrón útil, le permite crear algo y olvidarse de él, siempre que no almacene ninguna referencia al mismo y que finalmente lo termine. – Thomi