简体   繁体   English

Qt4中的析构函数

[英]destructors in Qt4

I'm very confused about using destructors in Qt4 and hope, you guys can help me. 我对在Qt4中使用析构函数感到非常困惑,并希望,你们可以帮助我。
When I have a method like this (with "Des" is a class): 当我有这样的方法时(“Des”是一个类):

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

how can I make sure that this widget is going to be deleted after it was closed? 如何确保此小部件在关闭后将被删除?

And in class "Des" i have this: 在课堂上“Des”我有这个:

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

where and how do I have to delete *push and *layout? 在哪里以及如何删除* push和* layout? what should be in the destructor Des::~Des() ? 什么应该在析构函数Des :: ~Des()?

Qt uses what they call object trees and it's a bit different from the typical RAII approach. Qt使用他们称之为对象树的东西 ,它与典型的RAII方法略有不同。

The QObject class constructor takes a pointer to a parent QObject . QObject构造函数获取指向父QObject的指针。 When that parent QObject is destructed, its children will be destroyed as well. 当该父QObject被破坏时,其子代也将被销毁。 This is a pretty prevalent pattern throughout Qt's classes and you'll notice a lot of constructors accept a *parent parameter. 这是Qt类中非常流行的模式,您会注意到很多构造函数都接受*parent参数。

If you look at some of the Qt example programs you'll find that they actually construct most Qt objects on the heap and take advantage of this object tree to handle destruction. 如果你看一些Qt 示例程序,你会发现它们实际构建了堆上的大多数Qt对象,并利用这个对象树来处理破坏。 I personally found this strategy useful as well, as GUI objects can have peculiar lifetimes. 我个人认为这个策略也很有用,因为GUI对象可以有特殊的生命周期。

Qt provides no additional guarantees beyond standard C++ if you're not using QObject or a subclass of QObject (such as QWidget ). Qt提供任何额外的保障超出标准C ++,如果你不使用QObject或子类QObject (如QWidget )。


In your particular example there's no guarantee that anything gets deleted. 在您的特定示例中,无法保证删除任何内容。

You'll want something like this for Des (assuming Des is a subclass of QWidget ): 你会想要Des这样的东西(假设DesQWidget的子类):

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
    }
}

And you'd use class Des like so: 你会像这样使用类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
}

Another option to using deleteLater() , or parents, is to use the delete-on-close functionality for widgets. 使用deleteLater()或parent的另一个选择是使用小部件的delete-on-close功能。 In this case, Qt will delete the widget when it is done being displayed. 在这种情况下,Qt将在完成显示时删除它。

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

I like to use it with the object tree that Qt keeps, so that I set delete-on-close for the window, and all widgets in the window have a proper parent specified, so they all get deleted as well. 我喜欢将它与Qt保留的对象树一起使用,因此我为窗口设置了delete-on-close,并且窗口中的所有窗口小部件都指定了正确的父窗口,因此它们也都被删除了。

Richardwb's answer is a good one - but the other approach is to use the deleteLater slot, like so: Richardwb的答案很好 - 但另一种方法是使用deleteLater插槽,如下所示:

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

Obviously the closed() signal can be replaced with whatever signal you want. 显然,闭合()信号可以用你想要的任何信号代替。

This tutorial suggests you don't need to explicitly delete widgets that have been added to parent widgets. 本教程建议您不需要显式删除已添加到父窗口小部件的窗口小部件。 It also says it doesn't hurt to do delete them either. 它还说删除它们也没有什么坏处。

(I've not tested this, but I guess as long as you explicitly delete them before the parent widget is deleted, this should be OK.) (我没有测试过这个,但我想只要你在删除父窗口小部件之前明确删除它们,这应该没问题。)

In most cases you should create widgets on the stack: 在大多数情况下,您应该在堆栈上创建小部件:

    QPushButton push("neu");

This way, they get deleted when they become out of scope. 这样,当它们超出范围时,它们就会被删除。 If you really want to create them on the heap, then it's your responsibility to call delete on them when they are not needed anymore. 如果你真的想在堆上创建它们,那么当你不再需要删除时,你有责任对它们进行调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM