C++ (Qt)class A{public: ssc::signal<void> sig;};
C++ (Qt)class B : public ssc::trackable{public: int slot() const { // Вот например с такой функцией return 123; }};
C++ (Qt)template <class T>inline void smart_ptr<T>::try_destroy(){ if (!_obj) return; if ((*_counter) == 1) { delete _counter; _counter = 0; delete _obj; _obj = 0; }}
C++ (Qt)template <class T>inline void smart_ptr<T>::try_destroy(){ if (!_obj) return; if ((*_counter)-- == 1) { delete _counter; _counter = 0; delete _obj; _obj = 0; }}
C++ (Qt)// не методы классаT_return (*fun_type)(T_arg1, T_arg2);T_return (*fun_type)(T_arg1);T_return (*fun_type)(); // методы классаT_return (T_receiver::*mem_fun_type)(T_arg1, T_arg2);T_return (T_receiver::*const_mem_fun_type)(T_arg1, T_arg2) const;T_return (T_receiver::*mem_fun_type)(T_arg1);T_return (T_receiver::*const_mem_fun_type)(T_arg1) const;T_return (T_receiver::*mem_fun_type)();T_return (T_receiver::*const_mem_fun_type)() const;
C++ (Qt)#include <iostream>#include <string>#include "signal_slot.h" void func(const std::string &str) { std::cout << "func slot: " << str << std::endl;} class A{public: A() { std::cout << "A()" << std::endl; } ~A() { std::cout << "~A()" << std::endl; } ssc::signal<const std::string &> sig_fun; /* теперь нужно тип аргумента расписывать подробно! И чтоб он в точности соответствовал арг. слота */ ssc::signal<int> sig_1; ssc::signal<const std::string &, int> sig_2; void run() const { sig_fun("Hello!"); sig_1(2011); sig_2("Hello World!", 1234567); }}; class B : public ssc::trackable{public: B() { std::cout << "B()" << std::endl; } ~B() { std::cout << "~B()" << std::endl; } void slot1(int x) const { std::cout << "slot1: x = " << x << std::endl; } int slot2(const std::string &str, int x) const { std::cout << "slot2: " << str << " x = " << x << std::endl; return 67; }}; int main(){ A *a = new A; B *b = new B; connect(a->sig_fun, func); connect(a->sig_1, b, &B::slot1); connect(a->sig_2, b, &B::slot2); a->run(); delete a; delete b; return 0;}
C++ (Qt)template <class T_arg1, class T_arg2 = void>class signal{ ... void operator() (T_arg1 arg1, T_arg2 arg2) const { for (_const_iterator it = _list.begin(); it != _list.end(); it++) { if ((*it)->valid()) (*it)->handle_evant(arg1, arg2); } }
C++ (Qt)template <class T_arg1, class T_arg2 = void>class signal{ ... template <class U1, class U2> void operator() (U1 arg1, U2 arg2) const { for (_const_iterator it = _list.begin(); it != _list.end(); it++) { if ((*it)->valid()) (*it)->handle_evant(arg1, arg2); } }
C++ (Qt)#include <iostream>#include <string>#include "signal_slot.h" class A{public: ssc::signal<int> sig_a; void run() const { sig_a(2011); }}; class B : public ssc::trackable{public: void slot_b(float x) { std::cout << "slot_b, x = " << x << std::endl; } }; class C : public ssc::trackable{public: C() {} ssc::signal<float> sig_c; void slot_c(int x) { sig_c(x); }}; int main(){ A *a = new A; B *b = new B; C *c = new C; // перенаправляет сигнал connect(a->sig_a, c, &C::slot_c); connect(c->sig_c, b, &B::slot_b); a->run(); delete b; delete a; delete c; return 0;}
C++ (Qt)#include <iostream>#include <string>#include "signal_slot.h" class A{public: ssc::signal<int> sig_a; ssc::signal<const std::string &> sig_a2; void run() const { sig_a(2011); sig_a2("Hello!"); }}; class B : public ssc::trackable{public: void slot_b(float x) { std::cout << "slot_b, x = " << x << std::endl; } void slot_b2(std::string str) { std::cout << str << std::endl; } }; int main(){ A *a = new A; B *b = new B; connect(a->sig_a, b, &B::slot_b); connect(a->sig_a2, b, &B::slot_b2); a->run(); delete b; delete a; return 0;}
C++ (Qt)ssc::signal<int, float> sig;
C++ (Qt)void slot1();void slot2(int);void slot3(int, float); // (float, int); (double, double); (int, int) и т.д.
C++ (Qt)#include <iostream>#include <string>#include "signal_slot.h"#include <cmath> class A{public: ssc::signal<int> sig_a2; ssc::signal<const double &, int> sig_a; void run() const { sig_a(M_PI, 123); sig_a2(1); }}; class B : public ssc::trackable{public:/* Класс B имеет 2 перегруженных слота */ void slot_b(float x, int y) { std::cout << "slot_b, x = " << x << std::endl; std::cout << "slot_b, y = " << y << std::endl; } void slot_b() { std::cout << "slot_b" << std::endl; } void other_slot() { std::cout << "other slot" << std::endl; } }; int main(){ A *a = new A; B *b = new B; /* Для того, чтоб не смущать компилятор, нужно в этом случае явно указывать типы шаблонов */ ssc::connect<B, void, float, int, const double&, int>(a->sig_a, b, &B::slot_b); ssc::connect<B, void, const double &, int>(a->sig_a, b, &B::slot_b); /* А здесь всё как обычно, компилятор сам справится */ ssc::connect(a->sig_a2, b, &B::other_slot); a->run(); delete b; delete a; return 0;}
C++ (Qt)spy->set(false);
C++ (Qt)#ifndef TRACKABLE_H#define TRACKABLE_H #include "smart_ptr.h" namespace ssc { class trigger{public: trigger() : _flag(true) {} void set(bool flag) { _flag = flag; } bool get() const { return _flag; } private: bool _flag;};//----------------------------------------------------------------------------- class trackable{public: trackable() { spy = smart_ptr<trigger>(new trigger); } virtual ~trackable() { spy->set(false); // Вот это должно быть атомарным? } smart_ptr<trigger> spy;};//----------------------------------------------------------------------------- } /* namespace ssc*/ #endif // TRACKABLE_H
C++ (Qt)class trigger{public: trigger() : _flag(true) {} bool get() const { return _flag; } friend class trackable; private: void set(bool flag) { _flag = flag; } bool _flag;};
C++ (Qt)void disconnect_all() // разрывает все сондинения
C++ (Qt)size_t slot_count() const // колличество всех соединений
C++ (Qt)template <class T_arg1, class T_arg2>class messenger2{public: template <class T1, class T2> messenger2(const messenger2<T1, T2> &other) : arg1(other.arg1), arg2(other.arg2) {} messenger2() {} messenger2(const T_arg1 &_arg1, const T_arg2 &_arg2) : arg1(_arg1), arg2(_arg2) {} T_arg1 arg1; T_arg2 arg2;};//----------------------------------------------------------------------------- template <class T1, class T2>inline bool operator== (const messenger2<T1, T2> &p1, const messenger2<T1, T2> &p2){ return ((p1.arg1 == p2.arg1) && (p1.arg2 == p2.arg2));}//----------------------------------------------------------------------------- template <class T1, class T2>inline bool operator!= (const messenger2<T1, T2> &p1, const messenger2<T1, T2> &p2){ return ((p1.arg1 != p2.arg1) || (p1.arg2 != p2.arg2));}//-----------------------------------------------------------------------------
C++ (Qt)#include <iostream>#include <string>#include "signal_slot.h"#include "messenger.h" using namespace std; typedef ssc::messenger4<int, int, string, int> dataA;typedef ssc::messenger4<float, double, string, int> dataB; class A{public: A() { cout << "A()" << endl; } ~A() { cout << "~A()" << endl; } void run() { sig_a1(3.14); sig_a2(dataA(1, 2, "Hello!", 3)); } ssc::signal<float> sig_a1; ssc::signal<const dataA &> sig_a2;};//----------------------------------------------------------------------------- class B : public ssc::trackable{public: B() { cout << "B()" << endl; } ~B() { cout << "~B()" << endl; } void slot_b1(int x) { cout << "slot_b(int), i = " << x << endl; } void slot_b2(const dataB &x) { cout << "slot_b2(const dataB &)" << endl; cout << x.arg1 << endl; cout << x.arg2 << endl; cout << x.arg3 << endl; cout << x.arg4 << endl; } void slot_b2(const dataA &x) { cout << "slot_b2(const dataA &)" << endl; cout << x.arg1 << endl; cout << x.arg2 << endl; cout << x.arg3 << endl; cout << x.arg4 << endl; } void slot_b2() { cout << "slot_b2()" << endl; }};//----------------------------------------------------------------------------- int main(){ A *a = new A; B *b = new B; a->sig_a1.connect(b, &B::slot_b1); // соединение с неперегруженным слотом /* Слот slot_b2 - перегружен, поэтому необходимо указывать явно параметры шаблонов */ a->sig_a2.connect<B, void, const dataB &>(b, &B::slot_b2); /* Note: сигнал отправляет тип dataA, а слот принимает тип dataB и это сработает! */ a->sig_a2.connect<B, void, const dataA &>(b, &B::slot_b2); a->sig_a2.connect<B, void>(b, &B::slot_b2); // И этот слот также сработает a->run(); delete a; delete b; return 0;}
C++ (Qt)template <class R_return>int connection_priority(R_return (*slot)()) const... // и так далее, для всех типов слотов
C++ (Qt)a.sig_a.connect(&b, &B::slot_b1, 1); // connection_priority = 1
C++ (Qt)template <class R_return, class R_arg>bool set_connection_priority(R_return (*slot)(R_arg), int priority)...
C++ (Qt)a.sig_a.set_connection_priority(&b, &B::slot_b4, 100); // connection_priority = 100
C++ (Qt)#include <iostream>#include "signal_slot.h" using namespace std; class A{public: ssc::signal<int> sig_a; void run() const { sig_a(123); }}; class B : public ssc::trackable{public: void slot_b1(int x) { cout << "slot_b1, x = " << x << endl; } void slot_b2(int x) { cout << "slot_b2, x = " << x << endl; } void slot_b3(int x) { cout << "slot_b3, x = " << x << endl; } void slot_b4() { cout << "slot_b4" << endl; } void slot_b5() { cout << "slot_b5" << endl; }}; int main(){ A a; B b; /* по умолчанию connection_priority = 0*/ a.sig_a.connect(&b, &B::slot_b1, 1); a.sig_a.connect(&b, &B::slot_b2, 2); a.sig_a.connect(&b, &B::slot_b3, 3); a.sig_a.connect(&b, &B::slot_b4, 4); a.sig_a.connect(&b, &B::slot_b5, 5); a.sig_a.set_connection_priority(&b, &B::slot_b4, 100); cout << "slot_b1, priority = " << a.sig_a.connection_priority(&b, &B::slot_b1) << endl; cout << "slot_b2, priority = " << a.sig_a.connection_priority(&b, &B::slot_b2) << endl; cout << "slot_b3, priority = " << a.sig_a.connection_priority(&b, &B::slot_b3) << endl; cout << "slot_b4, priority = " << a.sig_a.connection_priority(&b, &B::slot_b4) << endl; cout << "slot_b5, priority = " << a.sig_a.connection_priority(&b, &B::slot_b5) << endl; cout << endl; a.run(); return 0;}
C++ (Qt)#include <iostream>#include "signal_slot.h"#include <cmath> using namespace std; class A{public: ssc::signal<void> sig_a0; ssc::signal<int> sig_a1; ssc::signal<int, float> sig_a2; void run() const { sig_a0(); sig_a1(123); sig_a2(4, 2.5); }}; class B : public ssc::trackable{public: void slot_b0() { cout << "slot_b0" << endl; } void slot_b1(int x) { cout << "slot_b1, x = " << x << endl; } double slot_b2(double x, float y) { double res = pow(x, y); cout << "slot_b2, x^y = " << res << endl; return res; }}; int main(){ A a; B b; a.sig_a0.connect(&b, &B::slot_b0); a.sig_a1.connect(&b, &B::slot_b1); a.sig_a2.connect(&b, &B::slot_b2); a.run(); return 0;}
C++ (Qt)class A{public: ssc::signal<void> sig_a0; void run() const { sig_a0(); }}; class B : public ssc::trackable{public: void slot() const { cout << "slot B" << endl; }}; int main() { A a; B b; { B b_other; a.sig_a0.connect(&b_other, &B::slot); b_other = b; } a.run(); return 0;}
C++ (Qt)class trackable{public: trackable(const trackable &) { spy = counted_ptr<trigger>(new trigger); } trackable &operator=(const trackable &) { return *this; } // Оператор присваивания ничего не делает trackable() { spy = counted_ptr<trigger>(new trigger); } virtual ~trackable() { spy->set(false); } counted_ptr<trigger> spy;};
C++ (Qt) signal2(const signal2<S_arg1, S_arg2> &) {} // Пуст signal2<S_arg1, S_arg2> &operator=(const signal2<S_arg1, S_arg2> &) { return *this; } // Ничего не делает