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クラスコンストラクターは、親へのポインターを取りますQObject。その親QObjectが破壊されると、その子も破壊されます。*parentこれはQtのクラス全体でかなり一般的なパターンであり、多くのコンストラクターがパラメーターを受け入れることに気付くでしょう。

Qtサンプルプログラムのいくつかを見ると、それらが実際にヒープ上にほとんどのQtオブジェクトを構築し、このオブジェクトツリーを利用して破棄を処理していることがわかります。GUIオブジェクトには固有の存続期間がある可能性があるため、個人的にはこの戦略も役立つと思いました。

Qtは、 (などの)QObjectのサブクラスを使用していない場合、標準のC++以外の追加の保証を提供しません。QObjectQWidget


あなたの特定の例では、何かが削除されるという保証はありません。

次のようなものが必要になります(のサブクラスであると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
    }
}

そして、あなたは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");

このようにして、スコープ外になると削除されます。本当にヒープ上にそれらを作成したい場合は、それらが不要になったときに削除を呼び出すのはあなたの責任です。

于 2009-09-17T05:52:02.033 に答える