简体   繁体   English

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

[英]qt - what's the purpose of initialising child widgets in parent window/widget class?

In the VideoWidget and the Secure Socket Client examples in Qt, the code presented there initalises the child widgets in the parent widgets, like so: 在Qt中的VideoWidget和Secure Socket Client示例中,在那里呈现的代码将父窗口小部件中的子窗口小部件初始化,如下所示:

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

and

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

However, further down the code, I see the following: 但是,在代码中,我看到以下内容:

playButton = new QPushButton;

or in the case of the Secure Socket Client, this: 或者在安全套接字客户端的情况下,这个:

padLock = new QToolButton;

Why initalise in the constructor when it will be initalised in the code? 为什么在构造函数中将在代码中初始化时进行初始化?

Why initalise in the constructor when it will be initalised in the code? 为什么在构造函数中将在代码中初始化时进行初始化?

So that the implementation is exception safe. 这样实现是异常安全的。 Suppose that you'd have this code: 假设你有这个代码:

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

The destructor will delete padLock , but it has junk value, and you have undefined behavior. 析构函数将删除padLock ,但它有垃圾值,并且您有未定义的行为。 Recall that deleting a nullptr is safe (as is calling free(NULL) in C!). 回想一下,删除nullptr是安全的(就像在C中调用free(NULL) )。 The junk padlock value shows what happens when you don't initialize it. 垃圾挂锁值显示未初始化时发生的情况。 Throwing demonstrates that some intervening code may throw. 投掷表明可能会抛出一些干预代码。 Specifically, any intervening new will throw if the allocation can't succeed. 具体而言,如果分配不成功,任何介入的new都会抛出。 new does not return on failure (as in: it throws std::bad_alloc instead of returning, so the notion of return value doesn't apply at all). new不会在失败时返回(如:它抛出std::bad_alloc而不是返回,因此返回值的概念根本不适用)。

If one is writing idiomatic C++, then the pointer should not be a naked pointer, but a std::unique_ptr or QScopedPointer , and then this problem vanishes. 如果一个人正在编写惯用的C ++,那么指针不应该是一个裸指针,而应该是一个std::unique_ptrQScopedPointer ,然后这个问题就会消失。 You don't have to remember to initialize the pointer to zero, and you don't have to remember to clean it up. 您不必记住将指针初始化为零,并且您不必记得清理它。 RAII gives you a lot of win. RAII为您赢得了很多胜利。 That's the secret weapon that you get when you really use C++ the way it's meant to be used. 这是你真正使用C ++的秘密武器。

The C++ RAII idiom doesn't exist per se in any other common programming language. C ++ RAII习语本身并不存在于任何其他常见的编程语言中。 In languages that allow it (such as Java, C#, F#, Python, OCaml, and Common Lisp), the idiomatic work-around is to define a higher-order with_resource function, see examples for OCaml , Java and Python and Python again . 在允许它的语言中(例如Java,C#,F#,Python,OCaml和Common Lisp),惯用的解决方法是定义更高阶的with_resource函数, 再次参见OCamlJavaPython以及Python的示例。 Basically, in languages other than C++, and especially in garbage-collected languages, memory resource deallocation is handled differently from non-memory resource deallocation. 基本上,在C ++以外的语言中,特别是在垃圾收集语言中,内存资源释放的处理方式与非内存资源释放不同。 In C++, those are united under the RAII umbrella. 在C ++中,这些在RAII保护伞下统一起来。

It is good practice. 这是一种很好的做法。 You should always initialize your variables, even if it looks useless. 您应该始终初始化变量,即使它看起来没用。

This goes for local variables too. 这也适用于局部变量。 It is a good practice. 这是一个很好的做法。

Actually, if you do this: 实际上,如果你这样做:

QString str;

Then str is automatically initialized. 然后str自动初始化。 Unfortunately, if you do this: 不幸的是,如果你这样做:

int value;

Then value is not initialized to anything. 然后,值不会初始化为任何内容。 It's good for speed, but can often lead to bugs. 它对速度有好处,但通常会导致错误。

In case of a constructor, it is a good idea because if you change the code in the body, you may end up not initializing a variable or another... which could have been at least set to null in the list of initializers. 在构造函数的情况下,这是一个好主意,因为如果您更改正文中的代码,您可能最终不会初始化变量或其他...在初始化程序列表中至少可以设置为null。

There is also a reason in link with exceptions, but that's probably beyond Qt which doesn't use exceptions much. 链接异常也有一个原因,但这可能超出了Qt,它不会过多地使用异常。

Why initalise in the constructor when it will be initalised in the code? 为什么在构造函数中将在代码中初始化时进行初始化?

I believe it is just for the reason that if the actual instantiation is deferred to a different method later, for intance, you will not get an uninitialized member in the middle of some operation causing undefined behavior. 我相信这只是因为如果实际的实例化后来被推迟到另一个方法,对于intance,你将不会在某些操作的中间获得未初始化的成员导致未定义的行为。

However, in this particular case, it does not make much sense if the code is not planned to be modified any soon. 但是,在这种特殊情况下,如果不打算很快修改代码,则没有多大意义。

It might also boil down to coding styles in different projects, but in this special case, I am not aware of this being constrained by the official Qt coding style. 它也可以归结为不同项目中的编码风格,但在这种特殊情况下,我不知道这受到官方Qt编码风格的限制。 For instance, in the linux kernel, they prefer not to initialize it like this. 例如,在linux内核中,他们喜欢像这样初始化它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM