在父窗口/小部件类中初始化子小部件的目的是什么?

what's the purpose of initialising child widgets in parent window/widget class?

本文关键字:小部 是什么 初始化 窗口      更新时间:2023-10-16

在Qt中的VideoWidget和Secure Socket Client示例中,出现的代码初始化了父窗口小部件中的子窗口小部件,如下所示:

SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock(0), executingDialog(false)

VideoPlayer::VideoPlayer(QWidget *parent)
: QWidget(parent)
, mediaPlayer(0, QMediaPlayer::VideoSurface)
, playButton(0)
, positionSlider(0)
, errorLabel(0)

然而,在代码的后面,我看到了以下内容:

playButton = new QPushButton;

或者在安全套接字客户端的情况下,此:

padLock = new QToolButton;

为什么要在构造函数中初始化,而它将在代码中初始化?

当构造函数将在代码中初始化时,为什么要在构造函数中初始化?

因此实现是异常安全的。假设你有这样的代码:

SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock((QToolButton*)(0x0BEEF)), executingDialog(false) {
throw std::exception();
padLock = new QToolButton;
}

析构函数将删除padLock,但它具有垃圾值,并且您有未定义的行为。回想一下,删除nullptr是安全的(就像在C中调用free(NULL)一样!)。垃圾挂锁值显示了当你不初始化它时会发生什么。抛出表明了一些干预代码可能会抛出。具体来说,如果分配不能成功,任何介入的new都将抛出。new在失败时不返回(如:它抛出std::bad_alloc而不是返回,因此返回值的概念根本不适用)。

如果正在编写惯用C++,那么指针不应该是裸指针,而应该是std::unique_ptrQScopedPointer,然后这个问题就消失了。您不必记得将指针初始化为零,也不必记得清理它。RAII给了你很多胜利。当你真正按照C++的使用方式使用它时,这就是你得到的秘密武器。

C++RAII习语本身在任何其他通用编程语言中都不存在。在允许它的语言中(如Java、C#、F#、Python、OCaml和Common Lisp),惯用的解决方法是定义一个更高阶的with_resource函数,请再次参阅OCaml、Java和Python的示例。基本上,在C++以外的语言中,尤其是在垃圾收集语言中,内存资源释放的处理方式与非内存资源释放不同。在C++中,它们被联合在RAII的保护伞下。

这是一个很好的实践。您应该始终初始化您的变量,即使它看起来毫无用处。

这也适用于局部变量。这是一个很好的做法。

事实上,如果你这样做:

QString str;

然后str被自动初始化。不幸的是,如果你这样做:

int value;

则值不会初始化为任何值。它有利于速度,但经常会导致错误。

在构造函数的情况下,这是一个好主意,因为如果您更改主体中的代码,您可能最终不会初始化一个或另一个变量。。。其在初始化程序列表中可能至少被设置为null。

与异常的联系也是有原因的,但这可能超出了不太使用异常的Qt。

当构造函数将在代码中初始化时,为什么要在构造函数中初始化?

我相信这只是因为,如果稍后将实际实例化推迟到不同的方法,对于无形,您将不会在导致未定义行为的某些操作中获得未初始化的成员。

然而,在这种特殊的情况下,如果不计划很快修改代码,那就没有多大意义了。

它也可能归结为不同项目中的编码风格,但在这种特殊情况下,我不知道这会受到官方Qt编码风格的限制。例如,在linux内核中,他们更喜欢而不是这样初始化它。