深入理解c++實現(xiàn)Qt信號和槽機制
簡介
信號槽機制與Windows下消息機制類似,消息機制是基于回調(diào)函數(shù),Qt中用信號與槽來代替函數(shù)指針,使程序更安全簡潔。
信號和槽機制是 Qt 的核心機制,可以讓編程人員將互不相關的對象綁定在一起,實現(xiàn)對象之間的通信。
信號
當對象改變其狀態(tài)時,信號就由該對象發(fā)射 (emit) 出去,而且對象只負責發(fā)送信號,它不知道另一端是誰在接收這個信號。這樣就做到了真正的信息封裝,能確保對象被當作一個真正的軟件組件來使用。
槽
用于接收信號,而且槽只是普通的對象成員函數(shù)。一個槽并不知道是否有任何信號與自己相連接。而且對象并不了解具體的通信機制。
信號與槽的連接
所有從 QObject 或其子類 ( 例如 Qwidget ) 派生的類都能夠包含信號和槽。因為信號與槽的連接是通過 QObject 的 connect() 成員函數(shù)來實現(xiàn)的。
connect(sender, SIGNAL(signal), receiver, SLOT(slot));
其中 sender 與 receiver 是指向?qū)ο蟮闹羔?,SIGNAL() 與 SLOT() 是轉(zhuǎn)換信號與槽的宏。
特點
1、一個信號可以連接多個槽
當信號發(fā)射時,會以不確定的順序一個接一個的調(diào)用各個槽。
2、多個信號可以連接同一個槽
即無論是哪一個信號被發(fā)射,都會調(diào)用這個槽。
3、信號直接可以相互連接
發(fā)射第一個信號時,也會發(fā)射第二個信號。4、連接可以被移除
這種情況用得比較少,因為在對象被刪除時,Qt會自動移除與這個對象相關的所有連接。語法如下:
disconnect(sender, SIGNAL(signal), receiver, SLOT(slot));
觀察者模式
定義
觀察者模式(又被稱為發(fā)布-訂閱(Publish/Subscribe)模式,屬于行為型模式的一種,它定義了一種一對多的依賴關系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。這個主題對象在狀態(tài)變化時,會通知所有的觀察者對象,使他們能夠自動更新自己。
觀察者模式結(jié)構(gòu)圖
在觀察者模式中有如下角色:
1、Subject:抽象主題(抽象被觀察者),抽象主題角色把所有觀察者對象保存在一個集合里,每個主題都可以有任意數(shù)量的觀察者,抽象主題提供一個接口,可以增加和刪除觀察者對象。
2、ConcreteSubject:具體主題(具體被觀察者),該角色將有關狀態(tài)存入具體觀察者對象,在具體主題的內(nèi)部狀態(tài)發(fā)生改變時,給所有注冊過的觀察者發(fā)送通知。
3、Observer:抽象觀察者,是觀察者者的抽象類,它定義了一個更新接口,使得在得到主題更改通知時更新自己。
4、ConcrereObserver:具體觀察者,實現(xiàn)抽象觀察者定義的更新接口,以便在得到主題更改通知時更新自身的狀態(tài)。
實現(xiàn)簡單的信號和槽
為什么要說觀察者模式呢?因為Qt的信號和槽就是基于這種設計模式來進行設計的。通過信號和槽將對發(fā)送者信號感興趣的對象連接起來,當發(fā)送者的信號發(fā)送的時候,就會對這個列表進行遍歷,這種方式類似于廣播,不關心用戶是否收到,只是進行發(fā)送而已。下面是實現(xiàn)方式。
#include <iostream> #include <vector> using namespace std; //槽函數(shù)類 template <class TParam> class SlotBase { public: virtual void slotFuntion(TParam) = 0; virtual ~SlotBase() = default; }; template <class TReceiver,class TParam> class Slot:public SlotBase<TParam> { private: TReceiver *m_preveiver; void (TReceiver::*m_func)(TParam); public: Slot(TReceiver * reveiver,void(TReceiver::*func)(TParam)) { m_preveiver = reveiver; m_func = func; } void slotFuntion(TParam param) override { (m_preveiver->*m_func)(param); } }; //信號類 template <class TParam> class Signal { private: std::vector<SlotBase<TParam> *> signal_vector; public: template <class TReceiver> void addSlot(TReceiver *reveiver,void(TReceiver::*func)(TParam)) { signal_vector.push_back(new Slot(reveiver,func)); } void operator()(TParam param) { for(SlotBase<TParam> *p:signal_vector) { p->slotFuntion(param); } } }; //兩個測試的接受信號類 class Receiver1 { public: void func1(int param) { std::cout<<"這是Receiver1類中方法,參數(shù)為"<<param<<endl; } }; class Receiver2 { public: void func2(int param) { std::cout<<"這是Receiver2類中方法,參數(shù)為"<<param<<endl; } }; class SendObj { public: Signal<int> valueChanged; public: void testSend(int value) { valueChanged(value); } }; #define connect(send,signal,reveiver,slot) send->signal.addSlot(reveiver,slot) int main() { SendObj *send=new SendObj; Receiver1 *r1 = new Receiver1; Receiver2 *r2 = new Receiver2; connect(send,valueChanged,r1,&Receiver1::func1); connect(send,valueChanged,r2,&Receiver2::func2); send->testSend(100); return 0; }
到此這篇關于深入理解c++實現(xiàn)Qt信號和槽機制的文章就介紹到這了,更多相關c++實現(xiàn)Qt信號和槽機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C# interface與delegate效能比較的深入解析
本篇文章是對C#中interface與delegate的效能比較進行了詳細的分析介紹,需要的朋友參考下2013-05-05