8

C++ と Qt で GUI を作成する場合、たとえば次のようなラベルを作成できます。

QLabel* label = new QLabel("Hey you!", centralWidgetParent);

これにより、ヒープ上にオブジェクトが作成され、手動で削除するか、親が破棄されるまでそこにとどまります。私の質問は、なぜそのためのポインターが必要なのですか? スタック上に作成しないのはなぜですか?

//Create a member variable of Class MainWindow
QLabel label;

//Set parent to show it and give a text so the user can see it
    QWidget* centralWidget = new QWidget(this); //Needed to add widgets to the window
    this->setCentralWidget( centralWidget ); 
    label.setParent(centralWidget);
    label.setText( "Haha" );

これは正常に機能し、ラベルが表示され、消えませんでした。

C++ ではポインターを使用して何かを長生きさせ、さまざまなスコープでオブジェクトを使用できるようにします。しかし、メンバー変数を作成すると、オブジェクトが破棄されるまで残りませんか?

編集:多分私はそれを十分に明確にしませんでした。これは MainWindow クラスです。

class MainWindow : public QMainWindow
{
    Q_OBJECT
    QLabel label; //First introduced here...

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
};

//Constructor
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QWidget* centralWidget = new QWidget(this);
    this->setCentralWidget( centralWidget );
    label.setParent(centralWidget);
    label.setText( "Haha" );
}
4

5 に答える 5

8

labelスコープから外れると、デストラクタ ( QLabel::~QLabel) が呼び出されます。ドキュメントから:

オブジェクトを破棄し、そのすべての子オブジェクトを削除します。

ヒープ上にオブジェクトを作成する必要はありません。オブジェクトをスタックに置くこともできますが、その場合、オブジェクトの存続期間について責任を負う必要があります (ヒープ上にデータを割り当てることに関する最も問題のある問題の 1 つは、 「誰がいつこれらのオブジェクトを削除する必要がありますか?」、Qt では階層によって処理されます - ウィジェットを削除すると、すべての子ウィジェットが削除されます)。

あなたのプログラムが機能する理由 - わかりません - 機能しない可能性があります (labelはスコープの最後で破棄されます)。label別の問題は、参照がない場合、(たとえば、あるスロットから) テキストをどのように変更するかということです。

編集あなたlabelが のメンバーであることを確認しましたMainWindow。クラスのメンバーとしてのオブジェクトへのポインタではなく、完全なオブジェクトを持つことは完全に問題ありません。オブジェクトが存在する前に破棄されることはないからMainWindowです。MainWindow次のようなインスタンスを作成する場合は注意してください。

MainWindow *w = new MainWindow();

labelヒープ上に作成されます。

于 2013-09-24T14:56:43.090 に答える
6

それがQtの設計方法だからです。あまり満足のいく答えではないことは承知していますが、Qt は単純に「ウィジェットはヒープ上に作成され、親は子を削除する責任がある」ように設計されています。

Qt の起源は古いものであり、「最新の C++」と見なされるものよりも古いことを認識してください。

于 2013-09-24T14:56:19.630 に答える
5

心に留めておくべきもう 1 つのことは、Qt は、実際にインスタンス化するクラスの背後でオブジェクト データが暗黙的に共有および管理される、いわゆる pimpl パラダイムを使用することです。ここを参照してください: http://qt-project.org/wiki/Dpointer

肝心なのは、ヒープの使用を避けるためにスタックに割り当てている場合、Qt は高速なものを引っ張ってとにかくヒープを使用していることです。

于 2013-09-24T19:11:16.043 に答える
4

ウィジェットをローカル変数として割り当てることは、通常は良い考えではありません。はQObject「親子」関係 (C++ デストラクタとうまく統合されている) を介して構成パターンをサポートしているため、通常、最も簡単なことはそのような機能を利用することです。

一方、それをクラスのメンバーにする、一般に、親の寿命よりMainWindowも短い寿命を持つように任意の方法で割り当てることができます。実際、そのようなものが破棄されると、その親から自動的に登録解除され、二重の割り当て解除が回避されます。しかし、ウィジェットをヒープに割り当て、現在のウィンドウの子として登録する方が快適なことがよくあります。これは、通常、ウィジェットを作成した後に多くのウィジェット (ラベルなど) に実際にアクセスする必要がないため、乱雑にする必要がないためです。役に立たないデータメンバーを持つクラス。ウィンドウ コンストラクターを実行するだけで、それだけです。QLabelnew QLabel(this, ...)

代わりに、ウィジェットの有効期間が親の有効期間よりも長くなる場合 (たとえば、グローバル変数または静的変数に入れる)なしでウィジェットを割り当てることは、すべきではありません。 、せいぜいクラッシュ、最悪の場合サイレントメモリ破損を引き起こします。これは (クラス デストラクタでウィジェットを手動で登録解除することで) 修正できますが、そのようなことが役立つシナリオは想像できません。newdelete

于 2013-09-24T15:11:39.763 に答える