It seems that something could work better if a parent knows its children not only by layout.
You are right. A QObject
's parent is not only used for memory management purposes, this answer sums some of its other usages. The most important ones here are the ones of QWidget
's (since you are concerned about adding member QWidget
's), so if you use the second approach the way you are writing it, here are some of the issues you might get:
Suppose you are instantiating Widget1
and displaying it in your main function like this:
Widget1 w;
w.show();
This will display an empty widget without the button inside it. As opposed to the behavior when button
is a child of the Widget1
object, where calling show()
displays the widget parent with all of its children inside.
Similar issue happens when using setEnabled()
, setLayoutDirection()
, ...
button.pos()
won't return coordinates relative to Widget1
, in fact the button is not even displayed inside it. Same issue when using move()
.
The event system might not work as expected. So, if the member widget does not handle some mouse/keyboard event, the event won't propagate to the parent widget (since there is no parent specified).
But the second approach can be written to utilize the parent relationship with RAII, so that above issues are avoided:
class Widget2 : public QWidget
{
public:
explicit Widget2(QWidget* parent = nullptr):QWidget(parent){}
private:
QPushButton button{this}; //C++11 member initializer list
};
Or, in pre-C++11:
class Widget2 : public QWidget
{
public:
//initialize button in constructor, button's parent is set to this
explicit Widget2(QWidget* parent = Q_NULLPTR):QWidget(parent), button(this){}
private:
QPushButton button;
};
This way there aren't any differences to the Qt Framework between both approaches. In fact, using the second approach avoids dynamic allocation when unnecessary (Note that, this might have slightly better performance, if the allocation is executed very frequently in some nested loop for example. But, for most applications, performance is not really an issue here). So, you might be writing your widgets like this:
class Widget : public QWidget
{
public:
explicit Widget(QWidget* parent = nullptr):QWidget(parent){
//add widgets to the layout
layout.addWidget(&button);
layout.addWidget(&lineEdit);
layout.addWidget(&label);
}
~Widget(){}
private:
//widget's layout as a child (this will set the layout on the widget)
QVBoxLayout layout{this};
//ui items, no need to set the parent here
//since this is done automatically in QLayout::addWidget calls in the constructor
QPushButton button{"click here"};
QLineEdit lineEdit;
QLabel label{"this is a sample widget"};
};
This is perfectly fine, one might say that those child widgets/objects will be destroyed twice, first when they are out of scope and a second time when their parent is destroyed, making the approach unsafe. This is not an issue as once a child object is destroyed it removes itself from its parent's children list, see docs. So, each object will be destroyed exactly once.