我试图重写一个简单的“查找对话框”示例,而不使用指针作为类成员。我搞不懂为什么这段代码会导致这个例子崩溃
//finddialog.h
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include<QtWidgets>
//#include <QDialog>
class FindDialog : public QDialog
{
Q_OBJECT
public:
FindDialog(QWidget *parent = 0);
~FindDialog();
signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);
private slots:
void findClicked();
void enablefindButton(const QString &text);
private:
QLabel label{tr("Find &what:")};
QLineEdit lineEdit;
QCheckBox caseCheckBox{tr("Match &case")};
QCheckBox backwardCheckBox{tr("Search &bacward")};
QPushButton findButton{tr("&Find")};
QPushButton closeButton{tr("&Close")};
};
#endif // FINDDIALOG_H
这就是实现
//finddialog.cpp
#include <QtWidgets>
#include "finddialog.h"
FindDialog::FindDialog(QWidget *parent)
: QDialog(parent)
{
label.setBuddy(&lineEdit);
findButton.setDefault(true);
findButton.setEnabled(false);
connect(&lineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(enablefindButton(const QString &)));
connect(&findButton, SIGNAL(clicked()),
this, SLOT(findClicked()));
connect(&closeButton, SIGNAL(clicked()),
this, SLOT(close()));
QHBoxLayout topLeftLayout;
topLeftLayout.addWidget(&label);
topLeftLayout.addWidget(&lineEdit);
QVBoxLayout leftLayout;
leftLayout.addLayout(&topLeftLayout);
leftLayout.addWidget(&caseCheckBox);
leftLayout.addWidget(&backwardCheckBox);
QVBoxLayout rightLayout;
rightLayout.addWidget(&findButton);
rightLayout.addWidget(&closeButton);
rightLayout.addStretch();
QHBoxLayout mainLayout{this};
mainLayout.addLayout(&leftLayout);
mainLayout.addLayout(&rightLayout);
setLayout(&mainLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
}
FindDialog::~FindDialog()
{
}
void FindDialog::findClicked()
{
QString text = lineEdit.text();
Qt::CaseSensitivity cs = caseCheckBox.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
if (backwardCheckBox.isChecked())
emit findPrevious(text,cs);
else
emit findNext(text,cs);
}
void FindDialog::enablefindButton(const QString &text)
{
findButton.setEnabled(!text.isEmpty());
}
main就是这样的
//main.cpp
#include <QApplication>
#include "finddialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FindDialog w;
w.show();
return a.exec();
}
我发现问题出在方法'addLyout‘上,即注释所有对此方法的调用时,应用程序不会崩溃。在文档中,该方法需要一个指向QLayout的指针作为输入,所以我已经传递了每个布局的地址,但我遗漏了一些东西。你能帮我弄清楚是怎么回事吗?
发布于 2019-05-22 04:18:48
您的布局实例是堆栈变量,因此它们在构造函数返回后被销毁。其他对象现在具有指向不再存在的实例的指针。这通常意味着崩溃。
让你的布局实例成为FindDialog
的私有成员,以防止这种情况发生。
请注意,在堆栈上创建QObject实例时,需要注意声明顺序。当QObject被销毁时,它将删除其所有子对象,除非它们已经被销毁。这意味着你需要确保你的小部件在它们的布局被销毁之前被销毁。(这适用于所有具有父/子关系的QObjects,而不仅仅是布局。)如果你不注意这一点,父母会尝试删除堆栈中的孩子(显然,这是不允许的)。
类成员的销毁顺序与构造顺序相反。所以最后声明的成员首先被销毁。在QLayout子类的情况下,它们需要在它们的子部件之后被销毁。所以你需要先声明它们:
private:
QHBoxLayout topLeftLayout;
QVBoxLayout leftLayout;
QVBoxLayout rightLayout;
QHBoxLayout mainLayout{this};
QLabel label{tr("Find &what:")};
QLineEdit lineEdit;
QCheckBox caseCheckBox{tr("Match &case")};
QCheckBox backwardCheckBox{tr("Search &bacward")};
QPushButton findButton{tr("&Find")};
QPushButton closeButton{tr("&Close")};
这就是为什么你看到的大多数Qt代码都是在堆上分配QObjects (使用new
)的原因之一。在将它们放到堆上时,您不必担心这个问题。显然,当您拥有从未被删除的无父对象时,您可能会遇到内存泄漏。所以选择你的毒药吧。
https://stackoverflow.com/questions/56245573
复制相似问题