1. 元物件工具
元物件編譯器 moc(meta object compiler)對 c++ 檔案中的類宣告進行分析並產生用於初始化元物件的 c++ **,元物件包含全部訊號和槽的名字及指向這些函式的指標。
moc 讀 c++ 原始檔,如果發現有 q_object 巨集宣告的類,它就會生成另外乙個 c++ 原始檔,這個新生成的檔案中包含有該類的元物件**。例如,假設我們有乙個標頭檔案 mysignal.h,在這個檔案中包含有訊號或槽的宣告,那麼在編譯之前 moc 工具就會根據該檔案自動生成乙個名為 mysignal.moc.h 的 c++ 原始檔並將其提交給編譯器;類似地,對應於 mysignal.cpp 檔案 moc 工具將自動生成乙個名外 mysignal.moc.cpp 的檔案提交給編譯器。
元物件**是 signal/slot 機制所必須的。用 moc 產生的 c++ 原始檔必須和類實現一起進行編譯和鏈結,或用 #inldue 語句將其包含到類的原始檔中。moc 並不擴充套件 #include 或 #define 巨集定義,他只是簡單的跳過所遇見的所有預處理指令。
2. 程式示例
這裡給出了乙個簡單的示例程式,程式中定義了三個訊號、三個槽函式,然後將訊號和槽進行關聯,每個槽函式值是簡單的彈出乙個對話方塊視窗。
訊號和槽函式的宣告一般位於標頭檔案中,同時在類宣告單的開始位置必須加上 q_object 語句,這條語句是不可或缺的,它將告訴編譯器在編譯之前必須先應用 moc 工具進行擴充套件。關鍵字 signals 指出隨後開始訊號的宣告,這裡 signals 用的是複數形式而非單數,signals 沒有 public、private、protected 等屬性,這點不同於 slots。另外,signal、slots 關鍵字是 qt 自己定義的,不是 c++ 中的關鍵字。
訊號的宣告類似於函式的宣告而非變數的宣告,左邊要有型別,右邊要有括號,如果要向槽中傳遞引數的話,在括號中指定每個引數的型別,當然,形式引數的個數能多於乙個。
關鍵字 slots 指出隨後開始槽的宣告,這裡 slots 用的也是複數形式。
槽的宣告和普通寒時候的宣告相同,能攜帶零或多個形式引數。既然訊號的宣告類似於普通 c++ 函式的宣告,那麼,訊號也可採用 c++ 中過載函式的形式進行宣告,即同名但引數不同。例如,第一次定義的 void mysignal 沒有帶引數,而第二次定義的卻帶有引數,從這裡我們能看到 qt 的訊號機制是非常靈活的。
訊號和槽之間的聯絡必須事先用 connect 函式進行指定。如果要斷開二者之間的聯絡,使用函式 disconnect。
#ifndef mainwindow_h
#define mainwindow_h
#include namespace ui
class mainwindow : public qmainwindow
;#endif // mainwindow_h
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include mainwindow::mainwindow(qwidget *parent) :
qmainwindow(parent),
ui(new ui::mainwindow)
mainwindow::~mainwindow()
void mainwindow::myslot()
void mainwindow::myslot(int x)
void mainwindow::myslotparam(int x, int y)
void mainwindow::on_pushbutton_clicked()
3. 應注意的問題
訊號和槽機制是比較靈活的,但有些侷限性我們必須了解,這樣在實際的使用過程中才能做到有的放矢,避免產生一些錯誤。
(1)訊號和槽的效率是非常高的,不過同真正的**函式比起來,由於增加了靈活性,因此在速度上海市有所損失,當然這種損失相對來說是比較小的,通過在一台 i586-133 的集市上測試是 10 微秒(執行linux),可見這種機制所提供的簡潔性、靈活性還是值得的。但如果我們要追求高效率的話,比如在實時系統中就要盡可能的少用這種機制。
(2)訊號和槽機制和普通函式的呼叫相同,如果使用不當的話,在程式執行時也有可能產生死迴圈。因此,在定義槽函式時一定要注意避免間接形成無限迴圈,即在槽中再次發射所接受到的同樣訊號。例如,在前面給出的例子中如果在 myslot 槽函式中加上語句 emit sginal 即可形成死迴圈。
(3)如果乙個訊號和多個槽相聯絡的話,那麼,當這個訊號被發射時,與之相關的槽被啟用的順序是隨機的。
(4)巨集定義不能用在 signal 和 slot 的引數中。既然 moc 工具不擴充套件 #define,因此, 在 signals 和 slots 中攜帶引數的巨集就不能正確地工作,如果不帶引數則是可以的。
(5)建構函式不能用在 signals 或 slots 宣告區域內。
(6)函式指標不能作為訊號或槽的引數。
class someclass:public qobject
//但是,可以通過採用函式指標的 typedef 來繞過這個限制
class someclass:public qobject
(7)訊號和槽不能有預設值。
既然 signal/slot 繫結時發生在執行時的,那麼,從概念上講使用預設引數是困難的。
(8)訊號和槽也不能攜帶模板類引數。
如果將訊號、槽宣告為模板類引數的話,即時 moc 工具不報告錯誤,也不可能得到預期的結果。
(9)巢狀的類不能位於訊號或槽區域內,也不能有訊號或槽。
(10)友元宣告不能位於訊號或才宣告區內。相反,它們應該在普通 c++ 的 private、protected或public 區內進行宣告。
qt03訊號與槽
訊號與槽的關係就像是,嗯,比如,老師說下課了 發出訊號 然後同學a睡覺 接收下課訊號,執行睡覺的槽函式 同學b去上廁所 接收下課訊號,執行上廁所的槽函式 然後有乙個觀察者與被觀察者的概念,上面的例子中,老師是被觀察者,學生是觀察者,被觀察者發出訊號,觀察者接收並執行相應的函式,在qt中很多類都有內建...
qt 槽與訊號
槽就是乙個可以被呼叫處理特定訊號的函式 乙個小的qt類如下 class foo public qobject public slots void setvalue int signals void valuechanged int private int val qt中的元物件系統是用來處理物件間通...
QT訊號與槽
初學qt,覺得理解qt訊號與槽比較重要,qt很多時候都需要用到訊號和槽。發射訊號會觸發相對應的槽函式的執行。乙個訊號可以對應多個槽,多個訊號可以對應乙個槽。訊號和槽是通過connect這個方法進行建立聯絡的。qt中有些類會自帶有一些訊號和槽函式,當然訊號和槽函式也可以自己定義。下面來看下很簡單的 會...