C++ 簡單實現訊號槽
阿新 • • 發佈:2021-01-09
原理:儲存函式繫結類的函式指標,進行回撥。
1.訊號引數為指定個數,指定型別
#include <iostream> #include <stdlib.h> #include <vector> using namespace std; class SlotBase { public: virtual void Exec(int param1) = 0; virtual ~SlotBase() {} }; template<class T> class Slot :public SlotBase { typedef void (T::*Func)(int); public: Slot(T* pOjb, Func func) { m_func = func; m_pSlotBase = pOjb; } void Exec(int param1) { (m_pSlotBase->*m_func)(param1); } private: T* m_pSlotBase = NULL; Func m_func; }; class Signal { public: template<class T> void Bind(T* obj, void (T::*func)(int)) { m_pSlotSet.push_back(new Slot<T>(obj, func)); } void operator()(int param1) { for (int i = 0; i < (int)m_pSlotSet.size(); i++) { m_pSlotSet[i]->Exec(param1); } } private: vector< SlotBase* > m_pSlotSet; }; class TestFunc1 { public: void FunOfA(int param) { cout << __FUNCTION__ << " " << param << endl; } }; class TestSignal { public: TestSignal() { } void emit(int value) { ValueChanged(value); } public: Signal ValueChanged; }; #define Connect(sender,signal,receiver,method)((sender)->signal.Bind(receiver,method)); int main() { TestFunc1* pFunc1 = new TestFunc1; TestSignal* pSinal1 = new TestSignal(); Connect(pSinal1, ValueChanged, pFunc1, &TestFunc1::FunOfA); pSinal1->emit(1); delete pFunc1; delete pSinal1; getchar(); return 0; }
2.訊號引數為指定個數,不定類
#include <iostream> #include <stdlib.h> #include <vector> using namespace std; template<class T> class SlotBase { public: virtual void Exec(T param1) = 0; virtual ~SlotBase() {} }; template<class T, class T1> class Slot :public SlotBase<T1> { typedef void (T::*Func)(T1); public: Slot(T* pOjb, Func func) { m_func = func; m_pSlotBase = pOjb; } void Exec(T1 param1) { (m_pSlotBase->*m_func)(param1); } private: T* m_pSlotBase = NULL; Func m_func; }; template <class T1> class Signal { public: template<class T> void Bind(T* obj, void (T::*func)(T1)) { m_pSlotSet.push_back(new Slot<T, T1>(obj, func)); } void operator()(T1 param1) { for (int i = 0; i < (int)m_pSlotSet.size(); i++) { m_pSlotSet[i]->Exec(param1); } } private: vector< SlotBase<T1>* > m_pSlotSet; }; class TestFunc1 { public: void FunOfA(int param) { cout << __FUNCTION__ << " " << param << endl; } }; class TestFunc2 { public: void FuncOfB(std::string param) { cout << __FUNCTION__ << " " << param.c_str() << endl; } }; template<class T1> class TestSignal { public: TestSignal() { } void emit(T1 value) { ValueChanged(value); } public: Signal<T1> ValueChanged; }; #define Connect(sender,signal,receiver,method)((sender)->signal.Bind(receiver,method)); int main() { TestFunc1* pFunc1 = new TestFunc1; TestFunc2* pFunc2 = new TestFunc2; TestSignal<int>* pSinal1 = new TestSignal<int>(); TestSignal<std::string>* pSinal2 = new TestSignal<std::string>(); Connect(pSinal1, ValueChanged, pFunc1, &TestFunc1::FunOfA); Connect(pSinal2, ValueChanged, pFunc2, &TestFunc2::FuncOfB); pSinal1->emit(1); pSinal2->emit("hahhaha"); delete pFunc1; delete pFunc2; delete pSinal2; delete pSinal1; getchar(); return 0; }
3.訊號引數為指定不定個數,不定型別
#include <iostream> #include <stdlib.h> #include <vector> using namespace std; template< class ...Args> class SlotBase { public: virtual void Exec(Args...args) = 0; virtual ~SlotBase() {} }; template<class T, class ...Args> class Slot :public SlotBase<Args...> { typedef void (T::*Func)(Args...); public: Slot(T* pOjb, Func func) { m_func = func; m_pSlotBase = pOjb; } void Exec(Args...args) { (m_pSlotBase->*m_func)(args...); } private: T* m_pSlotBase = NULL; Func m_func; }; template <class...Args> class Signal { public: template<class T> void Bind(T* obj, void (T::*func)(Args...)) { m_pSlotSet.push_back(new Slot<T, Args...>(obj, func)); } void operator()(Args...args) { for (int i = 0; i < (int)m_pSlotSet.size(); i++) { m_pSlotSet[i]->Exec(args...); } } private: vector< SlotBase<Args...>* > m_pSlotSet; }; class TestFunc1 { public: void FunOfA(int param) { cout << __FUNCTION__ << " " << param << endl; } }; class TestFunc2 { public: void FuncOfB(std::string param) { cout << __FUNCTION__ << " " << param.c_str() << endl; } }; class TestFunc3 { public: void FuncOfC(int parm1,std::string param2,float params3) { cout << __FUNCTION__ << " " << parm1 << " " << param2.c_str() << " " << params3 << endl; } }; template<class...Args> class TestSignal { public: TestSignal() { } void emit(Args...args) { ValueChanged(args...); } public: Signal<Args...> ValueChanged; }; #define Connect(sender,signal,receiver,method)((sender)->signal.Bind(receiver,method)); int main() { TestFunc1* pFunc1 = new TestFunc1; TestFunc2* pFunc2 = new TestFunc2; TestFunc3* pFunc3 = new TestFunc3; TestSignal<int>* pSinal1 = new TestSignal<int>(); TestSignal<std::string>* pSinal2 = new TestSignal<std::string>(); TestSignal<int,std::string,float>* pSinal3= new TestSignal<int, std::string, float>(); Connect(pSinal1, ValueChanged, pFunc1, &TestFunc1::FunOfA); Connect(pSinal2, ValueChanged, pFunc2, &TestFunc2::FuncOfB); Connect(pSinal3, ValueChanged, pFunc3, &TestFunc3::FuncOfC); pSinal1->emit(1); pSinal2->emit("hahhaha"); pSinal3->emit(1,"heheh",2.3f); delete pFunc1; delete pFunc2; delete pSinal2; delete pSinal1; delete pFunc3; delete pSinal3; getchar(); return 0; }