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關聯起來


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM