正确理解Widget::Widget(QWidget *parent) :QWidget(parent)这句话

原文:https://zhuanlan.zhihu.com/p/31310536

/********原文********/

最近很多学习Qt的小伙伴在我的微信公众号私信我,该如何理解下面段代码的第二行QWidget(parent)

1 Widget::Widget(QWidget *parent) :
2     QWidget(parent)
3 {
4
5 }

为了统一回复大家,小豆君特意写了这篇文章,方便初学者们学习。

在讲解原因之前,先请大家看下面的一个例子

 1 #include <iostream>
 2 using namespace std;
 3 class Base
 4 {
 5 public:
 6     Base() :m_num(0){
 7         cout << "this is Base()" << endl;
 8     }
 9     Base(int val):m_num(val){
10         cout << "this is Base(int val)" << endl;
11     }
12 private:
13     int m_num;
14 };

1 上方代码定义了一个基类Base,并且有两个构造函数,一个是默认构造函数,一个是有一个整型参数的构造函数。

 1 class BaseChild: public Base
 2 {
 3 public:
 4     BaseChild(){
 5         cout << "this is BaseChild()" << endl;
 6     }
 7     BaseChild(int val): Base(val){
 8         cout << "this is BaseChild(val)" << endl;
 9     }
10 private:
11     int m_num;
12 };

2 上方代码定义了一个BaseChild类,并继承Base类,同样的,它也定义了两个构造函数,一个默认,一个有整型参数。

1 int main(int argc, char *argv[])
2 {
3     BaseChild child1;
4     BaseChild child2(5);
5
6     return 0;
7 }

3 main函数实例化了两个子类实例,child1,child2。child1调用默认构造函数。child2调用有整型参数的构造函数。

现在,我们运行程序,会有如下打印:

看到了吗,我们发现:

  • 创建child1时,是先调用了Base的默认构造函数,再调用自己的默认构造函数
  • 创建child2时,是先调用了Base(int)这个构造函数,再调用自己的整型参数构造函数。

所以我们回头看BaseChild的构造函数

1 BaseChild(int val): Base(val){
2         cout << "this is BaseChild(val)" << endl;
3     }

细心的同学,可能早就发现了,初始化列表中的Base(val)正是调用了我们Base基类的有参构造函数,而这样的写法就刚好是我们开头代码中的那段

1 Widget::Widget(QWidget *parent) :QWidget(parent)

所以Widget是调用了QWidget下面的构造函数

1 QWidget(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());

所以得出如下总结:

总结: · 如果不指定构造函数,则派生类会调用基类的默认构造函数 · 派生类构造函数的初始化列表只能初始化派生类成员,不能直接初始化继承成员,如果想 要调用基类的有参构造函数,则可以在派生类的初始化列表中显示指定

以上总结,也告诉我们,当定义一个类时,最好为该类定义默认构造函数。

至此,我们明白了这个写法为什么会这样写。

好的,那么我们又提出一个问题,“调用QWidget(parent)这个构造函数,QWidget父类都做了哪些动作呢?”

下面是QWidget源码中的一部分节选:

 1 QWidget::QWidget( QWidget *parent, const char *name, WFlags f )
 2     : QObject( parent, name ), QPaintDevice( PDT_WIDGET ),
 3       pal( parent ? parent->palette()        // use parent‘s palette
 4            : *qApp->palette() )            // use application palette
 5 {
 6     if ( parent ) {
 7     QChildEvent *e = new QChildEvent( Event_ChildInserted, this );
 8     QApplication::postEvent( parent, e );
 9     }
10 }

大家从上面可以看出,如果parent参数非空的话,那么该构造函数使用了其父窗口的调色板,并且发送了QChildEvent事件,这会让新的窗口成为parent所指窗口的子窗口,那么当父窗口被删除时,子窗口也会自动的被删除。

这其实是用到了Qt对象树的概念,关于对象树,小豆君会在后面的分享中为大家介绍。

原文地址:https://www.cnblogs.com/lei-zi/p/11121059.html

时间: 2024-10-07 06:23:18

正确理解Widget::Widget(QWidget *parent) :QWidget(parent)这句话的相关文章

理解了郭德刚说的那句话

老郭说,远离那些动不动让你宽容大度的人,小心雷劈TA的时候你惹火上身.大概意思是这样吧. 开始时,我对我婆婆恨我老公的爷爷奶奶有点不是很理解,因为婆媳关系都有矛盾的,但是自己生了孩子了才理解她为什么那么恨她公婆. 我不恨我公婆,但是说实话感情从开始时的那种爱一个人就爱他的家人的那种和睦相处的想法,到现在真希望老死不相往来. 我们家带孩子一直是个大问题,现在尤其事情特别多,我怀孕反应大,我儿子没人带,我们家房子要装修,我老公加入创业公司(公婆他们当时积极鼓励)天天忙的加班很晚.这一切已经够忙的了吧

正确理解WPF中的TemplatedParent

(注:Logical Tree中文称为逻辑树,Visual Tree中文称为可视化树或者视觉树,由于名称不是很统一,文中统一用英文名称代表两个概念,况且VisualTreeHelper和LogicalTreeHelper也是WPF中提供的类名称) 众所周知WPF中的Logical Tree是逻辑上定义的元素层次树,而实际上显示在屏幕上的元素层次树是Visual Tree,Visual Tree是 (注:Logical Tree中文称为逻辑树,Visual Tree中文称为可视化树或者视觉树,由于

正确理解 AsyncTask,Looper,Handler三者之间的关系(基于android 4.0)

Looper 和Handler 是理解好AsyncTask的一个基础,我们可以先从这里开始,先给出一个主线程和子线程互相通信的例子. 1 package com.example.loopertest; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Looper; 7 import android.os.Message; 8

if __name__ == &#39;__main__&#39; 如何正确理解

今天刷知乎,突然看到这个问题,发现很多人都是简单的回答了一下,对于很多人来说,更准确的说应该是大部分的 Python 初学者,这样的回答很容易让人理解.所以这里我来做说一下,希望能把这个问题说明白. 先举一个例子:假设我们有一个add.py文件,里面的代码是这样: def add(a, b):    return a + badd(1,2)#用于测试上面函数是否正常 这里就是一个求两数之和的函数,然后我在另一个文件中调用这个模块,这个时候就会把add(1,2)也运行,但是我是不希望运行add(1

TableViewCell reuse 重用 我认为的正确理解与使用方法

其实有点失望,因为用google搜索“uitableviewcell dequeueReusableCellWithIdentifier”出来一堆堆资深博主的文章.看了看,大部分都是在解决一个问题:使用重用时cell显示混乱的问题.该问题本身并不让我失望,失望的是博主们的解释. 首先,回顾一下UITableViewCell的重用,其基本逻辑就是tableView一开始会创建一屏幕的cell(如果有那么多)并把他们标记(Identifier),之后用户上下滑动tableView时,使用Identi

正确理解Python函数是第一类对象

正确理解 Python函数,能够帮助我们更好地理解 Python 装饰器.匿名函数(lambda).函数式编程等高阶技术. 函数(Function)作为程序语言中不可或缺的一部分,太稀松平常了.但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性.那到底什么是第一类对象呢? 函数是对象 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性

正确理解“冬钓阴”和“冬钓阳”

转载请注明文章转载自 光威鱼竿价格表 冬季钓鱼一般都讲究冬钓阳,但是又有一种说法叫做冬钓阴,这里面咋一看有点矛盾,那么怎么来正确理解这两者呢? 先来说说什么是冬钓阴,冬钓阴可不是选择阴天出去钓鱼,在冬天,如果没有太阳的话,一般水面受冷风侵袭,水温会比较低,不大利于鱼的活动和觅食,而另外一些地方,比如岸边有密集树林或者有挡风的围墙等等,这些平时觉得比较阴暗地方的水面由于被挡住了风,所以水温会相对高一些,更适合鱼活动,选择这些个地方垂钓就是所谓的冬钓阴. 冬钓阳,顾名思义就是选择有太阳的日子出去钓鱼

正确理解SQL Server配置timeout相关选项

正确理解SQL Server配置选项"remote login timeout"和"remote query timeout" 查看配置选项的设置 sp_configure 远程登录超时 参考:https://msdn.microsoft.com/en-us/library/ms175136.aspx "The remote login timeout option specifies the number of seconds to wait befor

正确理解 LEAL (Load Effective Address) 指令

LEAL: leal S, D    ->    D ← &S 在 CSAPP (Computer Systems: A Programmer’s Perspective) 中,对 LEAL 指令用作简单算术运算的情况,给出了一个例子: For example, if register %edx contains value x, leal 7(%edx,%edx,4), %eax will set register %eax to 5x + 7. 正确理解逻辑为: 1. 设%edx的值为x