为什么QWidget是通过指针访问的

Why are QWidgets accessed by pointers?

本文关键字:指针 访问 QWidget 为什么      更新时间:2023-10-16

我是Qt5的新手,正在学习QWidget来开发应用程序。

我注意到在许多例子中,QWidget几乎总是通过指针访问的。例如:

#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本身?

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

为什么在您的示例中没有必要通过指针访问QWidget?因为当main()"结束"时,程序就结束了,小部件可能会被销毁。

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

这并不是QWidgets特有的:它适用于每个QObjects(Qt基本基类,其他一切都是从它派生的)。

这是Qt框架设计选择的结果。报价Qt文件:

QObject既没有复制构造函数,也没有赋值运算符。这是经过设计的。

[…]

主要结果是您应该使用指向QObject的指针(或指向您的QObject子类)否则,您可能会将QObject子类用作一个值。对于例如,如果没有复制构造函数,就不能使用QObject作为要存储在其中一个容器类中的值。你必须存储指针。

来源:

http://doc.qt.io/qt-5.5/qobject.html#no-复制构造函数

这种选择的基本原理在这里解释:

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

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

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

另一方面,QWidget只继承了QObject和QPaintDevice,正如您在这里看到的

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

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

您可以从这里研究堆栈和堆之间的差异