11

我对在 Qt4 中使用析构函数感到非常困惑,希望你们能帮助我。
当我有这样的方法时(“Des”是一个类):

void Widget::create() {
    Des *test = new Des;
    test->show();
}

我怎样才能确保这个小部件在关闭后会被删除?

在“Des”课上,我有这个:

Des::Des()
{
    QPushButton *push = new QPushButton("neu");
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(push);
    setLayout(layout);
}

我必须在哪里以及如何删除 *push 和 *layout?析构函数 Des::~Des() 应该是什么?

4

5 回答 5

21

Qt 使用他们所谓的对象树,它与典型的 RAII 方法有点不同。

QObject构造函数接受一个指向 parent 的指针QObject。当该父QObject级被销毁时,其子级也将被销毁。这是整个 Qt 类中非常普遍的模式,您会注意到很多构造函数都接受*parent参数。

如果您查看一些 Qt示例程序,您会发现它们实际上在堆上构造了大多数 Qt 对象,并利用此对象树来处理破坏。我个人发现这个策略也很有用,因为 GUI 对象可以有特殊的生命周期。

如果您不使用QObject或不使用QObject(例如QWidget)的子类,Qt 不会提供超出标准 C++ 的额外保证。


在您的特定示例中,不能保证任何内容都会被删除。

你会想要这样的东西Des(假设Des是 的子类QWidget):

class Des : public QWidget
{
    Q_OBJECT

public:
    Des(QWidget* parent)
    : QWidget(parent)
    {
        QPushButton* push = new QPushButton("neu");
        QHBoxLayout* layout = new QHBoxLayout(this);
        layout->addWidget(push); // this re-parents push so layout 
                                 // is the parent of push
        setLayout(layout);
    }

    ~Des()
    {
        // empty, since when Des is destroyed, all its children (in Qt terms)
        // will be destroyed as well
    }
}

你会Des像这样使用类:

int someFunction()
{
    // on the heap
    Des* test = new Des(parent); // where parent is a QWidget*
    test->show();
    ...
    // test will be destroyed when its parent is destroyed

    // or on the stack
    Des foo(0);
    foo.show();
    ...
    // foo will fall out of scope and get deleted
}
于 2009-09-17T06:47:01.350 回答
12

使用 或父母的另一种选择deleteLater()是使用小部件的关闭时删除功能。在这种情况下,Qt 将在显示完成后删除小部件。

Des *test = new Des;
test->setAttribute( Qt::WA_DeleteOnClose );
test->show();

我喜欢将它与 Qt 保留的对象树一起使用,因此我为窗口设置了 delete-on-close,并且窗口中的所有小部件都指定了正确的父级,因此它们也都被删除了。

于 2009-09-17T14:22:45.343 回答
5

Richardwb 的回答很好——但另一种方法是使用 deleteLater 插槽,如下所示:

Des *test = new Des;
test->show();
connect(test, SIGNAL(closed()), test, SLOT(deleteLater()));

显然,可以用您想要的任何信号替换 closed() 信号。

于 2009-09-17T07:50:50.153 回答
3

本教程建议您无需显式删除已添加到父小部件的小部件。它还说删除它们也没有什么坏处。

(我没有对此进行测试,但我想只要您在删除父小部件之前明确删除它们,这应该没问题。)

于 2009-09-17T05:58:45.020 回答
2

在大多数情况下,您应该在堆栈上创建小部件:

    QPushButton push("neu");

这样,当它们超出范围时,它们就会被删除。如果您真的想在堆上创建它们,那么您有责任在不再需要它们时对它们调用 delete。

于 2009-09-17T05:52:02.033 回答