有一个小部件声明顺序要遵循吗?
There's a widget declaration order to follow?
是否有在 Qt5 中声明小部件的顺序(也许还有 4 个)?
考虑以下代码片段:
(只是header的一部分帮我解释一下)
class ConfigDialog : public QDialog
{
Q_OBJECT
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
QLabel userLabel;
QLabel passLabel;
QLineEdit userEdit;
QLineEdit passEdit;
};
这按预期工作但只是更改为(重新排序声明):
class ConfigDialog : public QDialog
{
Q_OBJECT
QLabel userLabel;
QLabel passLabel;
QLineEdit userEdit;
QLineEdit passEdit;
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
};
这也有效,但是当 ConfigDialog
超出范围时会发生段错误。
我也在其他场景中看到过这种情况,但总是更改顺序可以解决此问题。
我的猜测是:您使 QGroupBox
成为其他一些小部件的 parent。
Qt 在 QObject
之间有一个 parent-child 关系的概念。 parent负责在自身被销毁时删除其children;假设那些 children 被分配在堆上 new
.
此外,C++ class 的数据成员按照它们在 class 中列出的顺序构造,并以相反的顺序销毁。
假设 userAuthBox
是 userLabel
的 parent(通过 setParent
调用,在您的情况下由 addWidget
执行)。在第一种情况下,userLabel
首先被销毁,并通知其 parent 这一事实,随后 userAuthBox
将其从其 child 小部件列表中删除,并且不再尝试删除它。
在第二种情况下,userAuthBox
首先被销毁,并在其指向 userLabel
的指针上使用 delete
。但是当然 userLabel
实际上并没有分配给 new
。该程序然后表现出未定义的行为。
TL;DR:是的!声明的顺序在 C++ 中有严格定义的含义。正如您碰巧注意到的那样,随机顺序将不起作用。
您没有显示所有代码。重要的是其中一个小部件是组框的子项。假设你有:
class ConfigDialog : public QDialog
{
// WRONG
Q_OBJECT
QLabel userLabel;
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
public:
ConfigDialog(QWidget * parent = 0) :
QDialog(parent),
dialogLayout(this),
userAuthLayout(&userAuthBox) {
// Here userLabel is parent-less.
Q_ASSERT(! userLabel.parent());
userAuthLayout.addWidget(&userLabel, 0, 0);
// But here userLabel is a child of userAuthBox
Q_ASSERT(userLabel.parent() == &userAuthBox);
}
};
默认析构函数将按以下顺序调用析构函数 - 就好像您在析构函数中编写了以下有效的 C++ 代码一样。
dialogLayout.~QVBoxLayout()
- 好的。此时,对话框只是无布局。所有子部件都保留。
userAuthLayout.~QGridLayout()
- 好的。此时,组框只是无布局。所有子部件都保留。
userAuthBox.~QGroupBox()
- 糟糕。由于 userLabel
是此对象的子对象,因此嵌套的 userAuthox.~QObject
调用将执行以下行的等效项:
delete &userLabel;
由于从未使用 new
分配 userLabel
,您会得到未定义的行为,并且在您的情况下会发生崩溃。
相反,您应该:
在其父项之后声明子控件和 QObject
。
如果可能,使用 C++11 值初始化,或在构造函数中列出初始化程序,以向维护者表明子项与父项之间存在依赖关系。
有关详细信息和 C++11 和 C++98 解决方案,请参阅 ,该解决方案将迫使所有流行的现代静态 C++ 代码分析器捕获错误。如果可以,请使用它们。
是否有在 Qt5 中声明小部件的顺序(也许还有 4 个)?
考虑以下代码片段:
(只是header的一部分帮我解释一下)
class ConfigDialog : public QDialog
{
Q_OBJECT
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
QLabel userLabel;
QLabel passLabel;
QLineEdit userEdit;
QLineEdit passEdit;
};
这按预期工作但只是更改为(重新排序声明):
class ConfigDialog : public QDialog
{
Q_OBJECT
QLabel userLabel;
QLabel passLabel;
QLineEdit userEdit;
QLineEdit passEdit;
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
};
这也有效,但是当 ConfigDialog
超出范围时会发生段错误。
我也在其他场景中看到过这种情况,但总是更改顺序可以解决此问题。
我的猜测是:您使 QGroupBox
成为其他一些小部件的 parent。
Qt 在 QObject
之间有一个 parent-child 关系的概念。 parent负责在自身被销毁时删除其children;假设那些 children 被分配在堆上 new
.
此外,C++ class 的数据成员按照它们在 class 中列出的顺序构造,并以相反的顺序销毁。
假设 userAuthBox
是 userLabel
的 parent(通过 setParent
调用,在您的情况下由 addWidget
执行)。在第一种情况下,userLabel
首先被销毁,并通知其 parent 这一事实,随后 userAuthBox
将其从其 child 小部件列表中删除,并且不再尝试删除它。
在第二种情况下,userAuthBox
首先被销毁,并在其指向 userLabel
的指针上使用 delete
。但是当然 userLabel
实际上并没有分配给 new
。该程序然后表现出未定义的行为。
TL;DR:是的!声明的顺序在 C++ 中有严格定义的含义。正如您碰巧注意到的那样,随机顺序将不起作用。
您没有显示所有代码。重要的是其中一个小部件是组框的子项。假设你有:
class ConfigDialog : public QDialog
{
// WRONG
Q_OBJECT
QLabel userLabel;
QGroupBox userAuthBox;
QGridLayout userAuthLayout;
QVBoxLayout dialogLayout;
public:
ConfigDialog(QWidget * parent = 0) :
QDialog(parent),
dialogLayout(this),
userAuthLayout(&userAuthBox) {
// Here userLabel is parent-less.
Q_ASSERT(! userLabel.parent());
userAuthLayout.addWidget(&userLabel, 0, 0);
// But here userLabel is a child of userAuthBox
Q_ASSERT(userLabel.parent() == &userAuthBox);
}
};
默认析构函数将按以下顺序调用析构函数 - 就好像您在析构函数中编写了以下有效的 C++ 代码一样。
dialogLayout.~QVBoxLayout()
- 好的。此时,对话框只是无布局。所有子部件都保留。userAuthLayout.~QGridLayout()
- 好的。此时,组框只是无布局。所有子部件都保留。userAuthBox.~QGroupBox()
- 糟糕。由于userLabel
是此对象的子对象,因此嵌套的userAuthox.~QObject
调用将执行以下行的等效项:delete &userLabel;
由于从未使用
new
分配userLabel
,您会得到未定义的行为,并且在您的情况下会发生崩溃。
相反,您应该:
在其父项之后声明子控件和
QObject
。如果可能,使用 C++11 值初始化,或在构造函数中列出初始化程序,以向维护者表明子项与父项之间存在依赖关系。
有关详细信息和 C++11 和 C++98 解决方案,请参阅