开发者

Qt: Can child objects be composed in their parent object?

开发者 https://www.devze.com 2023-03-10 07:38 出处:网络
In Qt, can I embed child widgets in their parent via composition, or do I have to create them with new?

In Qt, can I embed child widgets in their parent via composition, or do I have to create them with new?

class MyWindow : public QMainWindow
{
    ...
private:
    QPushButton myButton;
}

MyWindow::MyWindow ()
 : mybutton("Do Something", this)
{
   ...
}

The documentation says that any object derived from QObject will automatically destroyed when its parent is destroyed; this implies a call to delete, whcih in the above example would crash.

Do I have to use the following?

QPushButton* myButton;

myButton = new QPushButton("Do Something", this);

EDIT

The answers are quite diverse, and basically boil down to three possibilities:

  • Yes, composition is ok. Qt can figure out how the object was allocated and only delete heap-allocated objects (How does this work?)
  • Yes, composition is ok, but don't specify a parent, since the parent would otherwise call delete on the object (But won't a parent-less widget t开发者_开发百科urn into a top-level window?)
  • No, widgets always have to be heap-allocated.

Which one is correct?


The non-static, non-heap member variables are deleted when that particular object's delete sequence starts. Only when all members are deleted, will it go to the destructor of the base class. Hence QPushButton myButton member will be deleted before ~QMainWindow() is called. And from QObject documentation: "If we delete a child object before its parent, Qt will automatically remove that object from the parent's list of children". Hence no crash will occur.


Object trees & ownership answers your question. Basically when the child object is created on the heap it will be deleted by its parent.

On the other hand when the child object is created on the stack the order of destruction is important. The child will be destroyed before its parent and will remove itself from its parent's list so that its destructor is not called twice.

There is also an example in that link that shows problematic order of destruction.


The documentation says that any object derived from QObject will automatically destroyed when its parent is destroyed; this implies a call to delete

No. It implies a call to the destructor of that particular entity.

Say in your example, if MyWindow is destroyed, it means the destructor of the MyWindow has been called. Which in turn will call the destructor myButton which is implemented already in QPushButton.

If you have composite entity, just the destructor will be called on that entity but not delete and so it won't crash.

Parent child relationships in Qt doesn't require specifically to be in a stack or heap. It can be in anything.

A similar example in parent child relationship over a stack is over here.

HTH..


The object will be destroyed only when it has a parent pointer, so you can use:

MyWindow::MyWindow ()
 : mybutton("Do Something", 0)
{
   ...
}


You should create it on heap, since QObject will destroy it :

class MyWindow : public QMainWindow
{
    ...
private:
    QPushButton *myButton;
}

MyWindow::MyWindow ()
 : mybutton( new QPushButton( "Do Something", this) )
{
   ...
}


calling delete operator will not crash ur application, you can read the following quote

Qt's parent–child mechanism is implemented in QObject. When we create an object (a widget, validator, or any other kind) with a parent, the parent adds the object to the list of its children. When the parent is deleted, it walks through its list of children and deletes each child. The children themselves then delete all of their children, and so on recursively until none remain. The parent–child mechanism greatly simplifies memory management, reducing the risk of memory leaks. The only objects we must call delete on are the objects we create with new and that have no parent. And if we delete a child object before its parent, Qt will automatically remove that object from the parent's list of children.

note that the parent argument is NULL by default (default argument) this is QPushButton Constructor

QPushButton ( const QString & text, QWidget * parent = 0 )

so u can use

    MyWindow::MyWindow () : mybutton( new QPushButton( "Do Something") ){   ... }

and u can call delete on any component and any time

Qt will take care for this point


Let me just quote the source here.

816 QObject::~QObject()
817 {
818     Q_D(QObject);
819     d->wasDeleted = true;
820     d->blockSig = 0; // unblock signals so we always emit destroyed()
821 
   ...
924 
925     if (!d->children.isEmpty())
926         d->deleteChildren();
927 
928     qt_removeObject(this);
929 
930     if (d->parent)        // remove it from parent object
931         d->setParent_helper(0);
932 
933 #ifdef QT_JAMBI_BUILD
934     if (d->inEventHandler) {
935         qWarning("QObject: Do not delete object, '%s', during its event handler!",
936                  objectName().isNull() ? "unnamed" : qPrintable(objectName()));
937     }
938 #endif
939 }

    ...

1897 void QObjectPrivate::deleteChildren()
1898 {
1899     const bool reallyWasDeleted = wasDeleted;
1900     wasDeleted = true;
1901     // delete children objects
1902     // don't use qDeleteAll as the destructor of the child might
1903     // delete siblings
1904     for (int i = 0; i < children.count(); ++i) {
1905         currentChildBeingDeleted = children.at(i);
1906         children[i] = 0;
1907         delete currentChildBeingDeleted;
1908     }
1909     children.clear();
1910     currentChildBeingDeleted = 0;
1911     wasDeleted = reallyWasDeleted;
1912 }

So as you can see, QObject does indeed delete each of its children in the destructor. In addition, the destructor is executed before destructors of any members; so if the composite in question equals the parent – then member QObject won't have any chance to remove itself from the children list of its parent.

This, unfortunately, means that you cannot compose a QObject into its parent. But you can compose into other objects, as well as allocate on stack – as soon as you guarantee to destruct the object or reset its parent to 0 before the parent starts destructing.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号