2012-04-15 11 views
70

Diciamo che ho questo segnale:Uso emettono vs chiamando un segnale come se fosse una normale funzione in Qt

signals: 
    void progressNotification(int progress); 

ho da poco imparato a conoscere la parola chiave Emit in Qt. Fino ad ora, eseguivo i segnali semplicemente chiamandoli come una funzione normale. Così, invece di:

emit progressNotification(1000 * seconds); 

avrei scritto:

progressNotification(1000 * seconds); 

loro chiamata come quella sembrava funzionare, e tutti gli slot collegate eseguirà, in modo da non utilizzando la parola chiave Emit causare un comportamento diverso, o è solo zucchero sintattico?

+11

+1 Non si sa mai che "emettere" non è necessario. È strano, però, che tu abbia imparato a conoscere "emit" molto tempo dopo aver chiamato i segnali direttamente, poiché il sistema di slot del segnale è una delle prime cose da imparare su Qt. –

risposta

61

emit è solo zucchero sintattico. Se guardi l'output pre-processato della funzione che emette un segnale, vedrai che emit è appena finito.

La "magia" si verifica nel codice generato per la funzione di emissione del segnale, che è possibile osservare ispezionando il codice C++ generato da moc.

Ad esempio un segnale foo senza parametri genera questo funzione membro:

void W::foo() 
{ 
    QMetaObject::activate(this, &staticMetaObject, 0, 0); 
} 

E il codice emit foo(); è pre-trattati semplicemente foo();

emit è definita Qt/qobjectdefs.h (in open-source sapore della fonte comunque), come questo:

#ifndef QT_NO_EMIT 
# define emit 
#endif 

(La protezione di definizione consente di utilizzare Qt con altri framework che hanno nomi in conflitto tramite l'opzione di configurazione no_keywords QMake.)

+11

Sai se c'è mai stata un'implementazione (o un'implementazione pianificata) di un 'emit' che in realtà ha fatto più di niente? Trovo che avere lo 'zucchero sintattico' in questo caso confonda il novizio (o almeno io quando ero un utente Qt principiante) - sembra che qualcosa di magico o importante stia accadendo con la parola chiave pseudo-emit', quando non fa nulla - tutta la magia avviene in una normale funzione vecchia che crea 'moc' (' moc' è la magia per i segnali e gli slot Qt). 'emit' è una decorazione inutile che non fa altro che sembrare importante. –

+8

Emit non è "solo decorazione". 'emit' dice alla persona che sta leggendo la chiamata che sta per accadere la magia (cioè questo sta per attivare il codice in oggetti di questa classe potenzialmente non ascoltati, e queste chiamate potrebbero essere sincrone o asincrone), che è essenzialmente totalmente persa se si omette la parola chiave. Usalo. È auto-documentante. I "novizi" dovrebbero leggere i documenti e le esercitazioni e "emit" è sempre lì (comunque nei documenti ufficiali). Scoprire che puoi semplicemente chiamare la funzione dovrebbe accadere dopo aver "visto la luce" - non sei più un novizio in quel momento. – Mat

+14

Hmm, non sono sicuro di essere d'accordo con te su quanto sia importante la parola chiave 'emit''. Penso che avrei preferito che fosse utilizzata una convenzione di denominazione se è necessario chiarire che una chiamata di funzione è un segnale. –

-4

La seconda opzione implica che si sappia sempre quale sia il nome della funzione e i parametri della funzione e che l'oggetto a cui lo si sta inviando sia noto con quella particolare funzione. Questi due casi non sono sempre veri, quindi sono le due cose principali per cui sono stati fatti slot e segnali. "under-the-hood" il meccanismo di segnale e slot è solo una tabella con puntatori a tutte le funzioni connesse.

Inoltre, un'occhiata a questo pdf che spiega molto chiaramente la natura del meccanismo di segnali e slot: http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf

+0

Entrambi i modi richiedono conoscere il nome del segnale e i suoi parametri - lo stai emettendo, come potresti emettere qualcosa che non conosci? Entrambi hanno la stessa semantica, sono identici. – Mat

+0

Forse stai incasinando una chiamata di segnale con una chiamata slot diretta? Ma devo ammettere che mi sono anche interrogato sul titolo della domanda all'inizio, dal momento che non ho mai saputo che "emettere" era solo un no-op. Ma anche in questo caso leggendo la domanda il corpo dovrebbe aver chiarito le cose, quindi -1. –

3

Dopo 18 mesi ... Ho iniziato con i commenti sotto la risposta di @ Mat e stavo finendo di stanza rapidamente. Quindi la risposta.

IMO emit è né zucchero sintattico né una semplice parola chiave, nel senso che

  1. Si genera il codice (come spiegato da @Mat sopra),
  2. Aiuta il meccanismo connect riconoscono che effettivamente è un signal e
  3. Rende il segnale parte di un sistema "più grande", in cui segnali e risposte (slot) possono essere eseguiti in modo sincrono o asincrono, o in coda, a seconda di dove e come il segnale è stato emesso. Questa è una caratteristica estremamente utile del sistema segnale/slot.

L'intero sistema di segnale/slot è un idioma diverso da una semplice chiamata di funzione. Credo che provenga dal modello di osservatore. C'è anche una grande differenza tra uno signal e uno slot: un segnale non ha da implementare, mentre uno slot deve essere!

Stai camminando per la strada e vedi una casa in fiamme (un segnale). Componi 911 (collega il segnale di fuoco con lo slot di risposta 911). Il segnale era emesso solo, mentre lo slot è stato implementato dai vigili del fuoco. Può essere impreciso, ma tu hai l'idea. Diamo un'occhiata all'esempio di OP.

Alcuni oggetti di back-end sanno quanti progressi sono stati fatti. Quindi potrebbe semplicemente il segnale emit progressNotification(...). Spetta alla classe che visualizza la barra di avanzamento attuale, prendere questo segnale ed eseguirlo. Ma come si collega la vista a questo segnale? Benvenuti nel sistema di segnale/slot Qt. Si può ora concepire una classe manager (tipicamente un widget di ordinamento), che consiste in un oggetto vista e un oggetto di calcolo dati (entrambi essendo QObjects), può eseguire .

Non entriamo negli aspetti di progettazione della classe manager, ma è sufficiente dire che questo è il punto in cui il sistema segnale/slot brilla. Posso concentrarmi sulla progettazione di un'architettura molto pulita per la mia applicazione. Non sempre, ma spesso, trovo che I emetta solo segnali ma implementa gli slot.

Se è possibile utilizzare/chiamare un metodo di segnale senza mai emetterla, allora implica necessariamente che non hai mai avuto bisogno che funzionano come un segnale in primo luogo.

Problemi correlati