QT分析之QApplication的初始化

原文地址:http://blog.163.com/net_worm/blog/static/1277024192010097430321/

在开始分析之前交代一下,一是分析的QT在Window平台实现(其它OS类似);二、分析的手段为看源码+单步跟踪。有时候会让编译器产生预编译后的输出(使用-E参数),便于观察;三、分析得QT版本为4.5.3

下面是QT经典的Hello world程序

 1 #include <qapplication.h>
 2 #include <qpushbutton.h>
 3 #include <qfont.h>
 4
 5 int main( int argc, char **argv )
 6 {
 7  QApplication a( argc, argv );
 8  QPushButton quit( "Quit", 0 );
 9  quit.resize( 75, 30 );
10  quit.setFont( QFont( "Times", 18, QFont::Bold ) );
11  QObject::connect( &quit, SIGNAL(clicked()), &a, SLOT(quit()) );
12  quit.show();
13  return a.exec();
14 }

第一句声明了一个QApplication的对象,QApplication的类继承关系为:

1 QApplication : QCoreApplication : QObject

先观察QApplication的构造函数:

1 QApplication::QApplication(int &argc, char **argv)
2     : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
3 { Q_D(QApplication); d->construct(); }

这里先后做了三件事:新生成一个QApplicationPrivate对象并传递给QCoreApplication;宏Q_D;调用d->construct()。

看Q_D的定义:

1 #define Q_D(Class) Class##Private * const d = d_func()

Q_D(QApplication);展开后是:

1 QApplicationPrivate * const d = d_func();

在附近正好看到Q_Q的定义:

1 #define Q_Q(Class) Class * const q = q_func()

由此看到在QT的程序里最好不要定义d、q这样的变量。

所以d->construct()调用的其实是

1 QApplicationPrivate::construct();

那么这个construct()干了什么事呢?

 1 void QApplicationPrivate::construct()
 2 {
 3     initResources();          // 初始化资源
 4
 5     qt_is_gui_used = (qt_appType != QApplication::Tty);
 6     process_cmdline();     // 扫描分析命令行参数
 7     // Must be called before initialize()
 8     qt_init(  this, qt_appType  );  // 在initialize()之前必须执行的初始化,例如色彩、字体、键盘等
 9     initialize();
10     eventDispatcher->startingUp();
11
12 }

其中eventDispatcher->startingUp();实际调用的是:QEventDispatcherWin32::startingUp(),主要是注册事件分发器。

回来看QCoreApplication的构造过程,把QApplicationPrivate对象传递给QOjbec,然后调用init()。

1 QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
2     : QObject(p, 0)
3 {
4     init();
5     // note: it is the subclasses‘ job to call
6     // QCoreApplicationPrivate::eventDispatcher->startingUp();
7 }

我们先来看QCoreApplication::init()干了什么事呢?

 1 void QCoreApplication::init()
 2 {
 3     Q_D(QCoreApplication);
 4
 5     // Get the application name/instance if qWinMain() was not invoked
 6     set_winapp_name();  // 设置应用程序的名字
 7
 8     Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
 9     QCoreApplication::self = this;
10
11     QThread::initialize();  // 初始化线程
12
13     // use the event dispatcher created by the app programmer (if any)
14     if (!QCoreApplicationPrivate::eventDispatcher)
15         QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
16     // otherwise we create one
17     if (!QCoreApplicationPrivate::eventDispatcher)
18         d->createEventDispatcher();  // 生成事件分发
19     Q_ASSERT(QCoreApplicationPrivate::eventDispatcher != 0);
20
21     if (!QCoreApplicationPrivate::eventDispatcher->parent())
22         QCoreApplicationPrivate::eventDispatcher->moveToThread(d->threadData->thread);
23
24     d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
25
26     if (!coreappdata()->app_libpaths) {
27         // make sure that library paths is initialized
28         libraryPaths();  // 确认或设定DLL库的路径
29     } else {
30         d->appendApplicationPathToLibraryPaths();
31     }
32
33     qt_startup_hook();  // 目前是空函数
34 }

Object的构造又做了什么事情呢?

QObject::QObject(QObjectPrivate &dd, QObject *parent)     : d_ptr(&dd) 将QApplicationPrivate对象传递给d_ptr,这个d_ptr是什么呢?

我们看QObject的类定义,d_ptr是QObject中唯一的数据成员:

protected:     QObjectData *d_ptr; 至此,QApplication对象的初始基本分析完毕,除了很多初始化的动作之外,主要就是把QApplication和QApplicationPrivate关联起来

时间: 2024-12-14 18:17:04

QT分析之QApplication的初始化的相关文章

QT分析之QPushButton的初始化

原文地址:http://blog.163.com/net_worm/blog/static/127702419201001003326522/ 在简单的QT程序的第二行,声明了一个QPushButton的对象.先简单看看其初始化过程. QPushButton的类继承关系为: 1 QPushButton :public QAbstractButton :pubic QWidget :public QObject, public QPaintDevice QPushButton的构造: 1 QPus

Qt事件分发机制源码分析之QApplication对象构建过程

我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码: int main(int argc, char *argv[]) { QApplication application(argc, argv); CQDialog dialog(NULL); dialog.show(); return application.exec(); } 对应的步骤解释如下 1.构建QApplication对象 2.构建CQDialog主界面 3.主界面显示 4.QApplication对象进入事件循

《深入理解SPARK:核心思想与源码分析》——SparkContext的初始化(中)

<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析>一书第一章的内容请看链接<第1章 环境准备> <深入理解Spark:核心思想与源码分析>一书第二章的内容请看链接<第2章 SPARK设计理念与基本架构> 由于本书的第3章内容较多,所以打算分别开辟三篇随笔分别展现. <深入理解Spark:核心思想与源码分析>一

【spring源码分析】IOC容器初始化(总结)

前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正的bean对象. 总结 [spring源码分析]IOC容器初始化(一):主要分析了Spring是如何解析占位符以及BeanFactory的最终实现类DefaultListableBeanFactory. [spring源码分析]IOC容器初始化(二):以loadBeanDefinitions函数为切

Nouveau源码分析(六):NVIDIA设备初始化之nouveau_drm_load (3)

Nouveau源码分析(六) 上一篇中我们暂时忽略了两个函数,第一个是用于创建nvif_device对应的nouveau_object的ctor函数: // /drivers/gpu/drm/nouveau/core/engine/device/base.c 488 static struct nouveau_ofuncs 489 nouveau_devobj_ofuncs = { 490 .ctor = nouveau_devobj_ctor, 491 .dtor = nouveau_devo

Spring IOC 源码简单分析 04 - bean的初始化

### 准备 ## 目标 了解 Spring 如何初始化 bean 实例 ##测试代码 gordon.study.spring.ioc.IOC04_Initialization.java public class IOC04_Initialization { public static void main(String[] args) { Resource resource = new ClassPathResource("ioc/ioc04.xml"); DefaultListabl

Nouveau源码分析(三):NVIDIA设备初始化之nouveau_drm_probe

Nouveau源码分析(三) 向DRM注册了Nouveau驱动之后,内核中的PCI模块就会扫描所有没有对应驱动的设备,然后和nouveau_drm_pci_table对照. 对于匹配的设备,PCI模块就调用对应的probe函数,也就是nouveau_drm_probe. // /drivers/gpu/drm/nouveau/nouveau_drm.c 281 static int nouveau_drm_probe(struct pci_dev *pdev, 282 const struct

[QT]问题记录-控件初始化导致程序异常关闭

qt新手,在设置 pushButton 的字体颜色时,出现软件异常闭,代码如下: 按钮的初始化在  ui->setupUi(this); 前边,会出现一下问题. 解决办法:将按钮的初始化在  ui->setupUi(this); 后边即可解决这个问题. 这是个基础的知识.类似的问题有: http://www.qtcn.org/bbs/read.php?tid-48535.html 如果有小伙伴知道有类似的问题,麻烦请回复下,谢谢.

Sonar6.0应用之三:集成Eclipse实时代码质量分析(附Eclipse初始化)

Sonar通过插件的形式与Eclipse集成,可以实现实时代码质量分析,前提条件是sonar服务器已经正常工作. 一.启动eclipse,下载并安装sonar插件 安装完成插件后重启eclipse,再次打开后对需要代码质量检查的项目右击 配置sonar服务器的地址.登陆名.密码等. 可以搜索到已经在sonar服务器上构建好的项目名称加入 二.配置eclipse中的命令窗口,便于实时代码质量检查. 找到SonarLint,复选它的三个组件 可以开始对源代码的质量进行分析了 错误说明 -------