2

我是 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 本身?

4

3 回答 3

5

这并不特定于 QWidgets:对于每个 QObjects(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

于 2015-11-12T07:38:27.723 回答
5

这一切都与对象的生命周期和共享所有权有关。如果您在函数中的堆栈上创建一个对象,它将在作用域结束时被销毁。

在您的示例中,为什么不需要通过指针访问 QWidget?只是因为当 main() '结束'时,你的程序已经完成,并且小部件可能会被破坏。

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

于 2015-11-12T06:43:57.303 回答
3

QClass 的大小更大,您不想通过在堆栈内存中实例化它们来填满堆栈内存。

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

另一方面,QWidget 仅继承 QObject 和 QPaintDevice,如您在此处看到的

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

使用堆内存时必须非常小心,阅读内存管理的答案

您可以从这里研究堆栈和堆之间的区别

于 2015-11-12T06:23:48.833 回答