故事的背景是這樣的,我們在寫QT程序的時候或者在開始寫QT程序之前總會看到這樣的語句
QApplication app(argc, argv);
這是什麼呢?QApplication這個類是繼承QCoreApplication的,而QCoreApplication有繼承
QObject的,而QObject就是QT中最基本的基類,也就是QT的根基了,這裡就從QCoreApplication
說起吧,頭文件中有這樣的開始
class Q_CORE_EXPORT QCoreApplication : public QObject
Q_CORE_EXPORT是什麼呢?如果在編寫動態庫時,定義DLL符號,Q_GUI_EXPORT就是導出函數或者類
了,如果在應用程序中使用時,不定義Dll符號,Q_GUI_EXPORT就是導入類或者函數了,這裡當然是導
入了,我們寫的可是命令行的,不是編寫動態庫,下面就是一些函數和變量的定義了,看到這裡我震
驚了
QCoreApplication * instance ()
定義一個指向自己的實例,啊?這是要鬧哪樣啊?難道要調用自己不成,實現就在類內,因為是靜態的
static QCoreApplication *instance() { return self; }
就是返回一個self
static QCoreApplication *self;
是一個私有的靜態成員變量,實現在類外
QCoreApplication *QCoreApplication::self = 0;
這下算是知道這個self是做什麼的了,可是這裡有個疑問,連QCoreApplication自己都沒被創建
呢,哪來的指向QCoreApplication的指針存在呢?這裡個人的解釋是靜態成員的創建應該類創建之
前就已經存在了,至於這個指向暫且就不考慮了,或許系統會解決這個問題吧,這裡就當成是一個指
針吧。
這裡有必要看一下這個QCoreApplication類的構造函數
QCoreApplication::QCoreApplication(int &argc, char **argv) : QObject(*new QCoreApplicationPrivate(argc, argv)) { init(); QCoreApplicationPrivate::eventDispatcher->startingUp(); #if defined(Q_OS_SYMBIAN) && !defined(QT_NO_LIBRARY) // Refresh factoryloader, as text codecs are requested during lib path // resolving process and won't be therefore properly loaded. // Unknown if this is symbian specific issue. QFactoryLoader::refreshAll(); #endif #if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE) d_func()->symbianInit(); #endif }
下面看著有點暈了,這裡就只看init();這個函數,就在構造函數的下面,這裡的代碼更多了,
這裡只寫我們關注的一行
void QCoreApplication::init() { QCoreApplication::self = this; }
這裡對self進行了賦值,這就讓這個self指向了當前這個對象,而不是什麼也不指了,這個self就可
以代替當前對象來使用了,當然這只能在類內,因為self是私有的,要在類外使用是不是應該定義一
個共有成員函數什麼的,先把疑問留在這裡。
說完這個靜態成員變量self還是沒有解決這裡為什麼要鬧這樣的問題,原來我們在類定義的上一行看
到這樣的代碼
#define qApp QCoreApplication::instance()
定義了一個qApp宏,這個宏也就成了一個指針,指向的是自己,這樣做又有什麼用呢
當我們在主程序中定義了QCoreApplication app(argc, argv);對象的時候完全是不需要用qApp這
個宏的啊,但是如果出了主函數要用這個對象怎麼辦,傳嗎?這樣比較麻煩,QT用這個指向自己的東
東就是幫助我們解決這樣要在主函數外使用app這個對象的而找不到對象的苦惱。好了,在函數外你就
用qApp吧,這樣會不會有什麼問題呢?這個東西在內存嗎?嘿嘿,這是靜態的啊,就在內存呆著呢,大
膽的去用這個指向自己的宏指針吧,只要app沒析構這東東就一直在內存。
下面來說明一下QApplication,這個是從QCoreApplication繼承來的,
#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
在類定義前有一段這樣的代碼,這裡也是取self這個指向自己的指針但是要做一個類型轉換,至於這個類型轉換是否安全,我想應該是安全的,因為相當於是從基類往派生類轉換,基類有的應該是對拷貝的,但是這裡的static會不會對這個造成困擾還不是很清楚,總之,要轉換後這個qApp才能在主函數外使用。
這裡還要說明的是這個QCoreApplication是不是單例的問題,網上有很多人認為是單例,也有很多人贊成,但是我實踐了一下應該不是單例
for(int i = 0 ; i < 3 ; ++i) { QCoreApplication app; }
這裡這樣的操作時允許的,因為之前的已經析構了,QT中說的只允許創建一個是指在一個函數內,只能創建一個,這裡顯然不是,單例的實現一般都是通過私有構造函數來實現的,這裡的構造函數是共有的顯然不是單例的節奏。
本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1288735