Completa l’esempio usando Boost :: Signals per C ++ Eventing

Sono a conoscenza del tutorial su boost.org che si occupa di questo: Tutorial sui segnali di Boost.org , ma gli esempi non sono completi e in qualche modo semplificati. Gli esempi non mostrano i file di inclusione e alcune sezioni del codice sono un po ‘vaghe.

Ecco di cosa ho bisogno:
ClassA genera più eventi / segnali
ClassB sottoscrive questi eventi (possono iscriversi più classi)

Nel mio progetto ho una class di gestione dei messaggi di livello inferiore che solleva gli eventi in una class business che esegue l’elaborazione di tali messaggi e notifica l’interfaccia utente (wxFrames). Ho bisogno di sapere come questi potrebbero essere collegati (quale ordine, chi chiama chi ecc.).

Il codice seguente è un esempio di lavoro minimo di ciò che hai richiesto. ClassA emette due segnali; SigA invia (e accetta) nessun parametro, SigB invia un int . ClassB ha due funzioni che verranno emesse in cout quando viene chiamata ogni funzione. Nell’esempio c’è un’istanza di ClassA ( a ) e due di ClassB ( b e b2 ). main è usato per connettere e sparare i segnali. Vale la pena notare che ClassA e ClassB non conoscono l’un l’altro (cioè non sono vincolati in termini di tempo di compilazione ).

 #include  #include  #include  using namespace boost; using namespace std; struct ClassA { signal SigA; signal SigB; }; struct ClassB { void PrintFoo() { cout << "Foo" << endl; } void PrintInt(int i) { cout << "Bar: " << i << endl; } }; int main() { ClassA a; ClassB b, b2; a.SigA.connect(bind(&ClassB::PrintFoo, &b)); a.SigB.connect(bind(&ClassB::PrintInt, &b, _1)); a.SigB.connect(bind(&ClassB::PrintInt, &b2, _1)); a.SigA(); a.SigB(4); } 

Il risultato:

 foo
 Bar: 4
 Bar: 4

Per brevità ho preso alcune scorciatoie che non usereste normalmente nel codice di produzione (in particolare il controllo degli accessi è lassista e di solito "hide" la registrazione del segnale dietro una funzione come nell'esempio di KeithB).

Sembra che la maggior parte delle difficoltà in boost::signal sta abituando all'utilizzo di boost::bind . All'inizio è un po 'impegnativo! Per un esempio più complesso, è ansible utilizzare anche bind per colbind ClassA::SigA a ClassB::PrintInt anche se SigA non emette un int :

 a.SigA.connect(bind(&ClassB::PrintInt, &b, 10)); 

Spero possa aiutare!

Ecco un esempio dalla nostra base di codici. È stato semplificato, quindi non garantisco che verrà compilato, ma dovrebbe essere vicino. La sublocazione è la tua class A, e la Slot1 è la tua class B. Abbiamo un numero di slot come questo, ognuno dei quali si abbona a un diverso sottoinsieme di segnali. I vantaggi dell’utilizzo di questo schema sono che la Sublocazione non sa nulla di nessuno degli slot, e gli slot non devono necessariamente far parte di alcuna gerarchia di ereditarietà e hanno solo bisogno di implementare le funzionalità per gli slot di loro interesse. Usiamo questo per aggiungere funzionalità personalizzate nel nostro sistema con un’interfaccia molto semplice.

Sublocation.h

 class Sublocation { public: typedef boost::signal ContactSignal; typedef boost::signal EndOfSimSignal; void endOfSim(); void addPerson(Time t, Interactor::Ptr i); Connection addSignalContact(const ContactSignal::slot_type& slot) const; Connection addSignalEndOfSim(const EndOfSimSignal::slot_type& slot) const; private: mutable ContactSignal fSigContact; mutable EndOfSimSignal fSigEndOfSim; }; 

Sublocation.C

 void Sublocation::endOfSim() { fSigEndOfSim(); } Sublocation::Connection Sublocation::addSignalContact(const ContactSignal::slot_type& slot) const { return fSigContact.connect(slot); } Sublocation::Connection Sublocation::addSignalEndOfSim(const EndOfSimSignal::slot_type& slot) const { return fSigEndOfSim.connect(slot); } Sublocation::Sublocation() { Slot1* slot1 = new Slot1(*this); Slot2* slot2 = new Slot2(*this); } void Sublocation::addPerson(Time t, Interactor::Ptr i) { // compute t1 fSigOnContact(t, t1); // ... } 

Slot1.h

 class Slot1 { public: Slot1(const Sublocation& subloc); void onContact(Time t1, Time t2); void onEndOfSim(); private: const Sublocation& fSubloc; }; 

Slot1.C

 Slot1::Slot1(const Sublocation& subloc) : fSubloc(subloc) { subloc.addSignalContact(boost::bind(&Slot1::onContact, this, _1, _2)); subloc.addSignalEndSim(boost::bind(&Slot1::onEndSim, this)); } void Slot1::onEndOfSim() { // ... } void Slot1::onContact(Time lastUpdate, Time t) { // ... } 

Hai dato un’occhiata a boost / libs / signals / example ?

Migliora come QT fornisce la propria implementazione di segnali e slot. Di seguito sono riportati alcuni esempi della sua implementazione.

Connessione segnale e slot per namespace

Considera uno spazio dei nomi chiamato GStreamer

  namespace GStremer { void init() { .... } } 

Ecco come creare e triggersre il segnale

  #include ... boost::signal sigInit; sigInit.connect(GStreamer::init); sigInit(); //trigger the signal 

Connessione segnale e slot per una class

Considera una class chiamata GSTAdaptor con la funzione chiamata func1 e func2 con la seguente firma

 void GSTAdaptor::func1() { ... } void GSTAdaptor::func2(int x) { ... } 

Ecco come creare e triggersre il segnale

 #include #include ... GSTAdaptor g; boost::signal sigFunc1; boost::signal sigFunc2; sigFunc1.connect(boost::bind(&GSTAdaptor::func1, &g); sigFunc2.connect(boost::bind(&GSTAdaptor::func2, &g, _1)); sigFunc1();//trigger the signal sigFunc2(6);//trigger the signal 

Quando si compila l’esempio di MattyT con il boost più recente (a partire da 1.61), viene visualizzato un avviso

 error: #warning "Boost.Signals is no longer being maintained and is now deprecated. Please switch to Boost.Signals2. To disable this warning message, define BOOST_SIGNALS_NO_DEPRECATION_WARNING." 

Pertanto, puoi definire BOOST_SIGNALS_NO_DEPRECATION_WARNING per sopprimere l’avviso oppure passare facilmente a boost.signal2 modificando l’esempio di conseguenza:

 #include  #include  #include  using namespace boost::signals2; using namespace std;