PDA

View Full Version : Deleting a child widget



zgulser
12th December 2012, 13:20
Hi,

I have widget;


...

MyWidget my_widget = new MyWidget(parentWidget/*this*/);

...

when I delete the parent like;


delete parentWidget;

it deletes the child but it doesn't call the MyWidget's destructor right? If we want to call MyWidget's destructor, we need delete the child MyWidget explicitly like?



delete myWidget;

Kwakkie
12th December 2012, 15:27
Your destructor will be called when the parent of the widget is deleted. You probably have a derived class and no virtual destructor?

zgulser
12th December 2012, 15:38
Hi,

It's virtual but somehow deletion performed implicitly.

anda_skoa
12th December 2012, 18:55
You probably have a derived class and no virtual destructor?

In a QWidget subclass you always have a virtual destructor because it inherits its virtualness from the destructor of the root base class, which is QObject and this one has a virtual destructor.

So in a situation like this


class MyWidget : public QWIdget
{
//....
};

MyWidget *myWidget = new MyWidget;
QWidget *widget = myWidget;
QObject *object = myWidget;


A delete call on any of those variables will result in calls to ~MyWidget then ~QWidget then ~QObject

Cheers,
_

d_stranz
12th December 2012, 23:01
MyWidget my_widget = new MyWidget(parentWidget/*this*/);


This code won't even compile, so it obviously isn't what you are actually doing in your own code. If you meant to say (and are doing something like this in your own code):



MyWidget * my_widget = new MyWidget(parentWidget/*this*/);


then calling "delete parentWidget" will do exactly what anda_skoa said will happen.

But I can't think of any case in Qt where you would want to call delete on a widget instance; deletion is handled automatically by the Qt parent-child ownership framework. Typically the top-most widget in an application's GUI hierarchy (as well as modal dialogs and the like) are created on the stack, not by "new", and delete themselves when they leave scope. All other widgets are created with "new" and are assigned a parent, and that parent is then in charge of their lifetimes.

amleto
12th December 2012, 23:06
Just to give you an example of needing to call delete on a Qt class instance - if you remove an item from a QGraphicsScene then you have ownership and will need to delete it manually.

Kwakkie
13th December 2012, 08:44
In a QWidget subclass you always have a virtual destructor because it inherits its virtualness from the destructor of the root base class, which is QObject and this one has a virtual destructor.

So in a situation like this


class MyWidget : public QWIdget
{
//....
};

MyWidget *myWidget = new MyWidget;
QWidget *widget = myWidget;
QObject *object = myWidget;


A delete call on any of those variables will result in calls to ~MyWidget then ~QWidget then ~QObject

Cheers,
_

I know that, But what if he has class A that is derived from class B, and B is derived from QWidget. If B has no virtual destructor...

zgulser
13th December 2012, 12:04
Hi,


This code won't even compile, so it obviously isn't what you are actually doing in your own code. If you meant to say (and are doing something like this in your own code):

Sure. But it seems a bit pointless highlighting to me:rolleyes:.


But I can't think of any case in Qt where you would want to call delete on a widget instance

mentioned "how can we" quite well above.


A delete call on any of those variables will result in calls to ~MyWidget then ~QWidget then ~QObject

I certainly agree and this is how I expected. But no destructor of MyWidget being called unless I delete it explicitly.

amleto
13th December 2012, 19:30
I know that, But what if he has class A that is derived from class B, and B is derived from QWidget. If B has no virtual destructor...

B MUST have virtual dtor since QObject has virtual dtor.


Hi,
I certainly agree and this is how I expected. But no destructor of MyWidget being called unless I delete it explicitly.

Show your example code. If MyWidget instance has a parent then the dtor will be called when the parent dies.

ChrisW67
14th December 2012, 00:08
But no destructor of MyWidget being called unless I delete it explicitly.
Sure they are. For a demo:

#include <QtGui>
#include <QDebug>
class MyWidget: public QWidget
{
Q_OBJECT
public:
MyWidget(const QString &name, QWidget *p = 0): QWidget(p) {
setObjectName(name);
qDebug() << "Constructed" << objectName();
}
~MyWidget() {
qDebug() << "Destroyed" << objectName();
}
};


int main(int argc, char **argv) {
QApplication app(argc, argv);

MyWidget *top = new MyWidget("top");
MyWidget *a = new MyWidget("a", top);
MyWidget *b = new MyWidget("b", top);
MyWidget *c = new MyWidget("c child of a", a);

delete top;

return 0;
}
#include "main.moc"



Constructed "top"
Constructed "a"
Constructed "b"
Constructed "c child of a"
Destroyed "top"
Destroyed "a"
Destroyed "c child of a"
Destroyed "b"


Perhaps in your real program you are not looking at or deleting the instances you think you are.

d_stranz
14th December 2012, 18:15
Just to give you an example of needing to call delete on a Qt class instance - if you remove an item from a QGraphicsScene then you have ownership and will need to delete it manually.

Yes, agreed. I think of this as a special case, though. Since QGraphicsScene contents are often dynamic, there needs to be special handling of item addition and removal. QWidget hierarchies are usually more static. But if you remove an item from a scene and that item itself has child items, when you delete the item, its children will automatically be deleted by the parent-child ownership protocol.



Constructed "top"
Constructed "a"
Constructed "b"
Constructed "c child of a"
Destroyed "top"
Destroyed "a"
Destroyed "c child of a"
Destroyed "b"


This is interesting - I thought "top" would have been shown as being destroyed last. My understanding of C++ construction was that construction proceeded from most-derived up to base class, and destruction proceeded from base class downward to most-derived, so the body of the destructor for the most-derived class would be executed last. Thus I would have expected that the messages for destruction would show "c", then "a", "b", and finally "top".

Obviously my understanding must be faulty, or is this behaviour an artifact of qDebug()?

Edit ---


My understanding of C++ construction was that construction proceeded from most-derived up to base class, and destruction proceeded from base class downward to most-derived,

Duh (after performing a head-whack) - no this is completely backward; construction goes up the hierarchy, with the body of the base class executed first, followed by each derived class, until finally the most-derived class's constructor gets executed. Destruction goes the other way. So the qDebug() statements as originally given do show things happening in the order they actually occur. My apologies for not having had enough coffee before starting to type.

amleto
14th December 2012, 18:26
This is interesting - I thought "top" would have been shown as being destroyed last. My understanding of C++ construction was that construction proceeded from most-derived up to base class, and destruction proceeded from base class downward to most-derived, so the body of the destructor for the most-derived class would be executed last. Thus I would have expected that the messages for destruction would show "c", then "a", "b", and finally "top".

Obviously my understanding must be faulty, or is this behaviour an artifact of qDebug()?

This isn't a demo of c++ inheritance hierarchy, it is Qt parent-child hierarchy example.

d_stranz
14th December 2012, 18:36
This isn't a demo of c++ inheritance hierarchy, it is Qt parent-child hierarchy example.

Well, yes it is, in a way. MyWidget is derived from QWidget and then from QObject, so I would expect that the body of ~QObject would be executed before the bodies of ~QWidget and ~MyWidget. This would imply that the children of the "top" widget (and the "a" widget) would be destructed by ~QObject (and thus their MyWidget destructors would execute) prior to the body of the MyWidget destructor for "top" getting executed. Thus the qDebug() statements should be issued in the order I stated.

I guess I'll just have to build this example and step through it in the debugger.

Edit -- never mind - see my edit a few posts above. I'll just slink away with my tail between my legs and work on why I can't get OpenGL textures to display in a QGLWidget.