PDA

View Full Version : How to destroy an object right



Cruz
22nd January 2009, 10:33
Hello!

I have a widget subclassing QFrame and it has a layout and lots of other widgets inside it. I'm wondering how to code the destructor right.



MyFrame::MyFrame(QWidget *parent) : QFrame(parent)
{
// Build inner parts.
QFrame *header = new QFrame;
QFrame *footer = new QFrame;

QHBoxLayout layout;
layout.addWidget(header);
layout.addWidget(footer);
setLayout(&layout);

SomeOwnObject someOwnObject = new SomeOwnObject();
}

MyFrame::~MyFrame()
{
if (someOwnObject != NULL)
delete someOwnObject;
}


I figure I do need to delete my own object. In the documentation it says that the widget takes ownership of the layout when setLayout(layout) is called and also that the layout takes ownership of a widget when layout->addWidget(widget) is called. So basicly I'm unsure if I somehow need to call the destructor of the superclass or maybe delete the layout.

jpn
22nd January 2009, 10:44
I figure I do need to delete my own object.
Yes, unless it's a QObject subclass and you pass a proper parent.


In the documentation it says that the widget takes ownership of the layout when setLayout(layout) is called
So why do you allocate it on the stack? :) It goes out of scope according to normal C++ rules, as soon as the constructor ends. You should allocate it on the heap.


and also that the layout takes ownership of a widget when layout->addWidget(widget) is called.
In fact layouts don't take ownership of widgets, but they will reparent them correctly so that "this" becomes the parent of "header" and "footer".


So basicly I'm unsure if I somehow need to call the destructor of the superclass or maybe delete the layout.
No, you don't need to delete the layout. QLayout is a QObject, and becomes a child of the widget when installed. Just allocate it on the heap as adviced.

Cruz
22nd January 2009, 10:51
Ok I understand the heap advice. What's still not clear to me is that if I call delete MyFrame somewhere, is the destructor of the superclass also called or do I have to do it manually?

And if so, actually how? I tried QFrame::~QFrame() and it didn't work.

spirit
22nd January 2009, 10:58
...
delete myWidget;
...

:)

jpn
22nd January 2009, 11:09
Ok I understand the heap advice. What's still not clear to me is that if I call delete MyFrame somewhere, is the destructor of the superclass also called or do I have to do it manually?

And if so, actually how? I tried QFrame::~QFrame() and it didn't work.
See C++ FAQ Lite: [11.12] When I write a derived class's destructor, do I need to explicitly call the destructor for my base class? (http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.12)

Cruz
22nd January 2009, 17:49
I still don't have full control of it. I'm trying to clear a layout from widgets. In the documentation it says



QLayoutItem * child;
while ((child = layout()->takeAt(0)) != 0)
{
delete child;
}


would safely clear a layout. When I use this, the widgets still stay on the screen. So I figure I need to cast the QLayoutItem* pointers to pointers to widgets of my kind, say MyWidget*. When I do that before deleting, the program crashes. Do I need to cast here actually?

Before I saw this in the documentation, I used an approach based on removeWidget(widget), but for that I need to keep a list of pointers to the widgets I added to the layout. It would be much more elegant to rely on the list of pointers that the layout itself is keeping.

jpn
22nd January 2009, 18:03
QLayoutItem represents an item in the layout. It's not a pointer to the widget. See QLayoutItem::widget(). But what are you actually trying to do? These kind of layout modifications tend to be problematic in terms of flickering etc. Perhaps you could just use a QStackedWidget?

Cruz
22nd January 2009, 19:43
I have a lot of QFrames coming in from an external source. They are placed on a widget say in a frame pool, so that the user can select a few of them and drag them somewhere else. After that the pool is cleared and new frames are coming in. So I'm looking for a short way to clear out the pool and the takeAt() method came to my attention.

Thanks for the hint, it works really well now. There is no flicker and I don't need to maintain an internal data structure to keep track of the frames.