前面我們說過,Qt 不是使用的“標(biāo)準(zhǔn)的” C++ 語言,而是對(duì)其進(jìn)行了一定程度的“擴(kuò)展”。這里我們從Qt新增加的關(guān)鍵字就可以看出來:signals、slots 或者 emit。所以有人會(huì)覺得 Qt 的程序編譯速度慢,這主要是因?yàn)樵?Qt 將源代碼交給標(biāo)準(zhǔn) C++ 編譯器,如 gcc 之前,需要事先將這些擴(kuò)展的語法去除掉。完成這一操作的就是 moc。
moc 全稱是 Meta-Object Compiler,也就是“元對(duì)象編譯器”。Qt 程序在交由標(biāo)準(zhǔn)編譯器編譯之前,先要使用 moc 分析 C++ 源文件。如果它發(fā)現(xiàn)在一個(gè)頭文件中包含了宏 Q_OBJECT,則會(huì)生成另外一個(gè) C++ 源文件。這個(gè)源文件中包含了 Q_OBJECT 宏的實(shí)現(xiàn)代碼。這個(gè)新的文件名字將會(huì)是原文件名前面加上 moc_ 構(gòu)成。這個(gè)新的文件同樣將進(jìn)入編譯系統(tǒng),最終被鏈接到二進(jìn)制代碼中去。因此我們可以知道,這個(gè)新的文件不是“替換”掉舊的文件,而是與原文件一起參與編譯。另外,我們還可以看出一點(diǎn),moc 的執(zhí)行是在預(yù)處理器之前。因?yàn)轭A(yù)處理器執(zhí)行之后,Q_OBJECT 宏就不存在了。
既然每個(gè)源文件都需要 moc 去處理,那么我們?cè)谑裁磿r(shí)候調(diào)用了它呢?實(shí)際上,如果你使用 qmake 的話,這一步調(diào)用會(huì)在生成的 makefile 中展現(xiàn)出來。從本質(zhì)上來說,qmake 不過是一個(gè) makefile 生成器,因此,最終執(zhí)行還是通過 make 完成的。
為了查看 moc 生成的文件,我們使用一個(gè)很簡(jiǎn)單的 cpp 來測(cè)試:
test.cpp
class?Test?:?public?QObject? {? ?Q_OBJECT? public:? ?explicit?Test(QObject?*parent?=?0);? signals:? public?slots:? };
這是一個(gè)空白的類,什么都沒有實(shí)現(xiàn)。在經(jīng)過編譯之后,我們會(huì)在輸出文件夾中找到 moc_test.cpp:
moc_test.cpp
/****************************************************************************? **?Meta?object?code?from?reading?C++?file?'test.h'? **? **?Created:?Thu?Jul?22?13:06:45?2010? **??????by:?The?Qt?Meta?Object?Compiler?version?62?(Qt?4.6.3)? **? **?WARNING!?All?changes?made?in?this?file?will?be?lost!? *****************************************************************************/? ? #include?"../test.h"? #if?!defined(Q_MOC_OUTPUT_REVISION)? #error?"The?header?file?'test.h'?doesn't?include."? #elif?Q_MOC_OUTPUT_REVISION?!=?62? #error?"This?file?was?generated?using?the?moc?from?4.6.3.?It"? #error?"cannot?be?used?with?the?include?files?from?this?version?of?Qt."? #error?"(The?moc?has?changed?too?much.)"? #endif? ? QT_BEGIN_MOC_NAMESPACE? static?const?uint?qt_meta_data_Test[]?=?{? ? ?//?content:? ???????4,???????//?revision? ???????0,???????//?classname? ???????0,????0,?//?classinfo? ???????0,????0,?//?methods? ???????0,????0,?//?properties? ???????0,????0,?//?enums/sets? ???????0,????0,?//?constructors? ???????0,???????//?flags? ???????0,???????//?signalCount? ? ???????0????????//?eod? };? ? static?const?char?qt_meta_stringdata_Test[]?=?{? ????"Test