Qt 代码问题可能与一般 C++ 有关
Posted
技术标签:
【中文标题】Qt 代码问题可能与一般 C++ 有关【英文标题】:Qt code questions perhaps pertaining to C++ in general 【发布时间】:2014-05-17 02:39:17 【问题描述】:我最近开始使用 Qt 框架,并意识到我可能不太了解 C++ 的语法。以在 Qt 中启动 Widget 项目时作为基础给出的这段代码为例。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
ui->setupUi(this);
MainWindow::~MainWindow()
delete ui;
其中MainWindow
类定义为:
namespace Ui
class MainWindow;
class MainWindow : public QMainWindow
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
;
类声明
通过这个,我可以看到创建了一个新的命名空间Ui
。我认为这是一种避免与其他用户实现的类发生命名冲突的实现工作。
下面是一个新的类定义;它继承了QMainWindow
,所以我们实际上是在创建一个自定义窗口对象。
Q_OBJECT
显然是一个允许用户在类定义中使用信号和槽的宏,但我现在并不太担心该代码。
我们将构造函数定义为explicit
,从而禁止此类类型的任何隐式转换。还显示了一个析构函数。
在私有访问中,我们查看Ui
命名空间并创建一个MainWindow
指针。
类定义
我们正在使用我看到的初始化列表,但我在这里迷路了。我看到这个小部件的父级有一个默认参数 NULL (或 0 ),但是如果一个类固有另一个类,为什么必须显式调用所述继承类的构造函数?那就是:
class A
class B : public A
B testObject;
这不会自动在堆栈上分配足够的内存来包含 A 类和 B 类吗?为什么上面显示的 Qt 代码在其自己的构造函数中调用继承类的构造函数?
继续初始化列表的第二个参数,我必须说我对这里使用的语法感到困惑。为什么我们有一个指向QMainWindow
的指针,我们通过调用QMainWindow
的构造函数并进一步调用new
来初始化它,从而创建它自己的一个实例?这种初始化方法似乎是循环的。
然后我们调用 setupUi 函数并传递 this
对象进行初始化。
最后,在析构函数中,我们简单地释放与MainWindow
关联的内存。
最后一个问题,如果创建了一个额外的对象,比如QPushButton
,软件会自动释放与这些对象相关联的内存,还是必须将其与delete ui
一起包含在析构函数中?我还没有看到实际执行此操作的教程,因此我不确定该框架是否设计为可以为您处理。
我知道这里很少有直接的问题,但我对每个陈述的逻辑是否有任何缺陷?
tl;dr,跳到类定义下的第一个和第二个项目符号。
【问题讨论】:
我的印象是在编译时会添加一个默认构造函数来初始化基础。 QMainWindow 继承的类呢?我知道类可能只调用其上一层的构造函数,但除非QMainWindow
的继承类有一些“包罗万象”的构造函数,否则我们会遇到一些麻烦。另外,谢谢你的收获!
【参考方案1】:
请注意,您不应该在一个问题中问这么多子问题,但无论如何我都会尝试回答您的问题...
这不会自动在堆栈上分配足够的内存来容纳 A 类和 B 类吗?
它为基类分配内存,是的。
为什么上面显示的 Qt 代码在其自己的构造函数中调用继承类的构造函数?
因为这就是 C++ 继承的工作原理。在这种情况下,您需要显式初始化基类它可能隐含在具有默认构造函数的理想中,但您甚至没有在这里使用它,这很好。
为什么我们有一个指向 QMainWindow 的指针,我们通过调用 QMainWindow 的构造函数并进一步调用 new 从而创建它自己的实例来初始化它?这种初始化方法似乎是循环的。
正如您在开始时所解释的,您有两个单独的 MainWindows,一个由 Qt 设计器生成,一个在您的代码中实现类,因此您提到了命名空间。
作为最后一个问题,如果创建了一个额外的对象,比如 QPushButton,软件是否会自动释放与这些对象关联的内存,还是必须将其与 delete ui 一起包含在析构函数中?我还没有看到真正做到这一点的教程,所以我不确定这个框架是否被设计成可以为你处理。
如果你在堆栈上分配它,则没有必要,因为它会在超出范围时自动销毁。如果您在堆上分配它,在 Qt 世界中,您将父级指定为构造函数的参数,以便在删除父级时自动删除它。这是由 Qt parent-child hierarchy and mechanism 为您透明地完成的。这就是为什么您通常在示例中看不到显式删除的原因。
【讨论】:
很好的解释。我仍然不确定您在帖子中回答的第三个问题。当我第一次在 Qt 中看到这个并编辑代码以使用它而不是上面显示的内容时,我感到很困惑:ui = new Ui::MainWindow;
(在它当前所在的块之外)。这对我来说完全有意义。我知道我们需要为这个对象分配堆,但是通过调用 new
来调用 MainWindow 的构造函数来为自己分配内存是循环的并且让我感到困惑。构造函数甚至会将什么作为参数? MainWindow(MainWindow*)
?
@sherrellbc:这里没有循环的东西。 new Ui::MainWindow
是 Ui
命名空间中的 UI 类,而 MainWindow::MainWindow
是 Ui
命名空间外部 的 MainWindow 类。您可以找到有关 C++ 命名空间in here 的更多信息。以上是关于Qt 代码问题可能与一般 C++ 有关的主要内容,如果未能解决你的问题,请参考以下文章