關於信號和插槽,Q_OBJECT
宏將虛擬函數qt_metacall()
聲明添加到類聲明中,該聲明稍後將由moc
定義。 (它也增加了一些聲明的轉換,但在這裏,這不是太重要。)
的moc
然後讀取頭文件,當它看到的宏時,它產生另一個.cpp
文件名爲moc_headerfilename.cpp
與定義,虛擬功能和 - 你可能會問自己,爲什麼你可以在頭文件中提到signals:
而沒有正確定義信號。
因此,當調用一個信號時,將執行mocfile的定義並調用QMetaObject::activate()
以及信號的名稱和信號的參數。 然後activate()
函數計算出哪些連接已建立並獲取相應插槽的名稱。
然後它調用qt_metacall
插槽名稱和給出的信號的參數和元調用功能代表這個藉助於一個大的switch
- case
聲明真實的插槽。
由於沒有關於對信號和槽的實際名稱可能在C中沒有真正運行時信息++,正如已經注意到了,這些將由SIGNAL
和SLOT
宏簡單const char*
s爲單位進行編碼(或者用「1」或「2」添加到該名稱以區分插槽中的信號)。
正如在qobjectdefs.h
定義:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
-
的Q_OBJECT
宏所做的就是定義你的目標內部的tr()
功能,它可以用來翻譯應用程序中的其他事情。
編輯 當你問什麼qt_metacast
正在做什麼。它檢查對象是否屬於某個類,如果它返回指向它的指針。如果不是,則返回0.
Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);
這是需要提供一些運行時反射,否則不可能。例如,該函數在QObject::inherits(const char *)
中調用,並簡單地檢查繼承。
dup:http://stackoverflow.com/questions/1406940/how-signal-and-slots-are-implemented-under-the-hood – elcuco 2010-01-05 20:45:22