为什么通过指针访问QWidgets?

时间:2015-11-12 05:41:35

标签: c++ qt pointers qtwidgets

我是Qt5的新手,我正在学习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本身?

3 个答案:

答案 0 :(得分:5)

这完全取决于对象的生命周期和共享所有权。如果在函数堆栈上创建一个对象,则当范围结束时它将被销毁。

为什么在您的示例中没有必要通过指针访问QWidget?只是因为当main()'结束'时,你的程序就完成了,而widget可能会被破坏。

为什么有必要通过指针访问QWidget的子节点?因为如果你想让QWidget让你访问它的孩子,它就不能给你一个值,因为它只是一个对象的副本。此外,如果按值将大对象传递给QWidget,则需要复制对象。

答案 1 :(得分:4)

这不是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

答案 2 :(得分:3)

QClasses规模较大,您不希望通过在堆栈内存中实例化来填充堆栈内存。

当你实例化派生类对象时,它还需要运行基类(派生类+基类)内存的构造函数,

另一方面,QWidget只继承了QObject和QPaintDevice,你可以看到How to remove duplicate items from a list using list comprehension?

因此,在堆栈内存上创建QWidget对象的开销会减少。

使用堆内存时必须非常小心,请阅读here

上的答案

您可以从memory management

研究堆栈和堆之间的区别