2015-11-12 120 views
2

我是Qt5的新手,我正在學習QWidgets來開發應用程序。爲什麼QWidgets通過指針訪問?

我注意到在很多例子中,QWidgets幾乎總是被指針訪問。例如:

#include <QApplication> 
#include <QWidget> 
#include <QFrame> 
#include <QGridLayout> 

class Cursors : public QWidget { 

public: 
    Cursors(QWidget *parent = 0); 
}; 

Cursors::Cursors(QWidget *parent) 
    : QWidget(parent) { 

    QFrame *frame1 = new QFrame(this); 
    frame1->setFrameStyle(QFrame::Box); 
    frame1->setCursor(Qt::SizeAllCursor); 

    QFrame *frame2 = new QFrame(this); 
    frame2->setFrameStyle(QFrame::Box); 
    frame2->setCursor(Qt::WaitCursor); 

    QFrame *frame3 = new QFrame(this); 
    frame3->setFrameStyle(QFrame::Box); 
    frame3->setCursor(Qt::PointingHandCursor); 

    QGridLayout *grid = new QGridLayout(this); 
    grid->addWidget(frame1, 0, 0); 
    grid->addWidget(frame2, 0, 1); 
    grid->addWidget(frame3, 0, 2); 

    setLayout(grid); 
} 

int main(int argc, char *argv[]) { 

    QApplication app(argc, argv); 

    Cursors window; 

    window.resize(350, 150); 
    window.setWindowTitle("Cursors"); 
    window.show(); 

    return app.exec(); 
} 

這是從教程採取:http://zetcode.com/gui/qt5/firstprograms/

然而,在同一頁上,我看到,我們可以通過它的對象本身訪問QWidget的基類:

#include <QApplication> 
#include <QWidget> 

int main(int argc, char *argv[]) { 

    QApplication app(argc, argv); 

    QWidget window; 

    window.resize(250, 150); 
    window.setWindowTitle("Simple example"); 
    window.show(); 

    return app.exec(); 
} 

爲什麼需要通過指針訪問所有QWidget派生類?爲什麼沒有必要通過指針訪問QWidget本身?

+0

兩者都不是必要的。在類方法中創建局部變量可能會更容易,而不是聲明一堆只會訪問一次的成員變量。既然你需要小部件在方法範圍之外生存,你可以用'new'來初始化它們。請參閱[對象樹和所有權](http://doc.qt.io/qt-5/objecttrees.html)。 – thuga

回答

4

這是學習所有關於對象的生命週期和共享所有權堆和棧的區別你必須非常小心。如果您在函數中創建堆棧中的對象,則在範圍結束時它將被銷燬。

爲什麼在您的示例中沒有必要通過指針訪問QWidget?只是因爲當main()'結束'時,你的程序完成了,widget可能被銷燬。

爲什麼需要通過指針訪問QWidget的子項?因爲如果你想讓QWidget讓你訪問它的孩子,它不能給你一個價值,因爲它只是一個對象的副本。此外,如果您將大對象按值傳遞給QWidget,則需要複製對象。

3

QClasses的大小較大,您不希望通過在堆棧內存中實例化它們來填滿堆棧內存。

當實例派生類對象它也運行一個基類(派生類+基類)的所需要的存儲器的構造,

在另一方面QWidget的僅繼承自QObject和的QPaintDevice你可以看到here

因此,在堆棧內存上創建QWidget對象的開銷會更小。

當您使用堆內存,讀取memory management

的答案可以從here

+2

一個類可能有幾個基於QWidget的對象成員,不需要指針,只要_owning_對象不在堆棧上,它們仍然不會在堆棧上。在這種情況下,基於QWidget的對象的成員和方法將不會被指針訪問。例如'myApplication-> frame1.setCursor(Qt :: PointingHandCursor)'或在對象'myApplication'中,它只是'frame1.setCursor(Qt :: PointingHandCursor)' –

+0

在堆上創建對象的好習慣?這是一個相當廣泛的聲明。 – Mitch

+0

在堆上創建對象及其指針。例如unique_ptr或shared_ptr –

3

這不是QWidgets特有的:對於每個QObject(Qt基礎類,從中派生出其他所有東西)都是如此。

這是Qt框架設計選擇的結果。引用Qt文檔:

QObject既沒有拷貝構造函數也沒有賦值運算符。 這是設計。

[...]

的主要後果是,你應該使用 指針的QObject(或您的QObject子類),您可能 否則會傾向於使用你的QObject子類的值。對於 示例,如果沒有複製構造函數,則不能使用QObject的子類作爲要存儲在其中一個容器類中的值。您必須存儲指針,您必須存儲 。

來源:

http://doc.qt.io/qt-5.5/qobject.html#no-copy-constructor

這一選擇的理由在這裏解釋:

http://doc.qt.io/qt-5.5/object.html#identity-vs-value

+0

加一個實際鏈接到主題的文檔。 – Mitch